Sproutcore versus Cappuccino
I've been using sproutcore for six months now, and cappuccino for three.
I have to say, that, at a first glance, I had no idea of what I would discover. At first Sproutcore seemed very application centric, much like Cappuccino seemed very immature.
Well, the reality was quite different. I'll try to be as objective as possible in the following comparison.
Sproutcore
Sproutcore or SC for short, provides different frameworks in a single package. SC also uses and comes with abbot, it's build tool. There is also a project named Amber, which is basically a stripped down version of SC usable in conjuction with other frameworks.
SC uses JQuery, it is now bundled with it. Early on it uses something derived from JQuery, but now the actual library is included.
While this is a good thing in the way it will leave JQuery developers unsurprised, it is nothing new, which is bad because we are trying to use better paradigm for webapp programming than for websites.
Layout engine
For me, the SC exprience started as something quite fun and interesting. I had very quickly a little app running. Things started to mess up as I decided to start my first project.
SC widget library is really incomplete and sometimes even not working (I could not have a select menu working, I had to roll my own). I realized that to produce a working application, I would have to implement a lot of widget and user interfaction myself. The whole SC experience started to make sense when I stopped to use built in views.
Now in my largest project, the only view class I use is SC.View and SC.ListView, and I also uses SC.Pane for floating content. This approach was advised by SC creators themself. I was told that SC was not to abstract from web technologies such as CSS or HTML, but to help, like JQuery helps.
To this extend, the only interesting feature of SC for layout is the binding system, you can create something like:
1 MyApp.MyView = SC.View.extend({
2 nameBinding:"MyApp.myValue",
3 render:function(ctx) {
4 ctx.push('<label>', this.get('name'), '</label>');
5 },
6 displayProperties:['name']
7 });
This is the typical view I had to write. This is great to have the binding system which will rerender the view when myValue changes, but it's really cumbersome to have to render html that way.
Update: I do not use the LabelView on purpose, why? Because the LabelView is quite heavy but also this is to show how to render something a little bit custom. Same goes with the button below, I do not use a ButtonView because the ButtonView is complex, and maybe I don't need or want this complexity. So those two example are here to show how it works when you need to write something custom, and according to my experience, this is what you end doing most of the time.
In the end, all my views render html by concatenating strings. For events, I use something like that (my button view):
1 MyApp.ButtonView = SC.View.extend({
2 render:function(ctx) {
3 ctx.push(this.get('label'));
4 },
5 tagName:'button',
6 didCreateLayer:function() {
7 this.$().click(function() {
8 // handle click, wrap in SC.RunLoop.begin() SC.RunLoop.end() if you run SC code
9 });
10 // or
11 SC.Event.add(this.$(), 'click', this, '_handler');
12 },
13 _handler:function() { // for second alternative
14 }
15 });
I don't know what you think, but I think this is very, very cumbersome.
Of course, SC implements mouseDown and other methods like that (which will be called on your views), but they are neither documented and keep changing from version to version.
I think SC will mature more and become more usable (templates has been added lately, to avoid string concatenation), but the goal is not to abstract you from the browser.
Datastore
SC datasstore is, by itself, a gem. If you know the EnterpriseObject framework, it's that but in javascript. The good side of the datastore is it's power, you can find, update, commit, destroy... your objects with ease. It supports a wide variety of queries through its query language.
The real power of the datastore is unleashed in combinaison with the binding system. In fact, the datastore can be used without the binding system, but it's cumbersome. The reason? The proxy objects.
When you do a query within the SC datastore, you will get an object back, wherever this object is loaded or not. If it is not loaded, it will be an empty proxy object.
Basically, this means you cannot do that:
1 var myObject = myStore.find(myQuery);
2 console.log(myObject.get('name'));
or, you can, but you will end printing null in your console if the object has not been loaded previously. The store is intended to be used this way:
1 // somewhere in an object
2
3 myProperty:function() {
4 return myStore.find(myQuery);
5 }.property()
6
7
8 myObject = SC.Object.create ({
9 objectBinding:'the object above.myProperty',
10 _nameDidChange:function() {
11 console.log(this.getPath('object.name'));
12 }.observe('*object.name')
13 });
The idea is that the object returned by myProperty will be a proxy object, and binding to it from another object will setup key value observing. Then we observe for the object change, and recursively for the name of that object (* denotes recursive bindings).
Now, while this might be a loved approach for some, I realized I hated that. It's the exact same comparison between what I call "offline ORM" and "online ORM" (bare with me, I just invented that), EnterpriseObjects framework, Oracle TopLink, Hibernate being in the first category and ActiveRecord being in the second category.
Why offline ORM are bad? They are not bad, but they are very hard to sync between multiple applications. EnterpriseObjects framework was an offline ORM, and it used pessimist locking by default to ensure syncing (like update from table where id = 2 and name = "old name" and ... for all the rows in the table, the update would fail if the record changed in between). ORM sitting near the DB can do pessimist locking, in fact offline ORM can have very good performances, but online ORM can be as good after some optimization, but it's more work. Now, a web application that load data with JSON can do something like pessimist locking, but it would be twice the data to send to the server (original data + updated data).
The other problem lies in syncing the other records. Even when you are the only app touching the database, it's very rare to have a model where when you update 1 object, only 1 record will change within the database. I mean, something like "/create_report" could create 20 objects in 25 tables, and your client app will have to load all that, and sync with it's current data. Now with SC it's actually doable. In one of my SC application, the rails server output all the object it touched in the request in a json dictionary like so:
1 {:update => {:model_name_A => [{:id => 2, :name => :toto},...], :model_name_B =>...}, :destroy => {...}, ...}
a lot of ... in there, but you get the idea.
We found that this approach works quite well, but in the end, what does it bring to us over a simpler framework? Nothing much.
Don't get me wrong, SC is a very good piece of software, it just doesn't work the way I need my web framework to work.
Conclusion
In the end, SC was very clumzy at layout and page rendering. It was a lot of pain to produce even the simplest widgets. The binding system is really powerful, if you like it. Also there is more to come like Greenhouse, but I just felt I could not bare with the framework anymore, but I suggest you try it to make your own opinion.
Pro:
- Easy to start with
- Community is getting stronger
- Used by some big companies (Apple)
- Stable (when your app is built with statechart and properly designed, it will be solid, SC is stable)
- Datastore can be a gem if your architecture can fit it
- Use things you are used to (JQuery, SASS...)
- Binding system is amazing, but you need to think your app adaptively to use them
Cons:
- Layout by concatenating strings is awful, template engine is here but still, I'm violated for the rest of my life
- Build tools can complicated and not polished, I found by pure luck the use of sc-build
- Widgets are broken, unusable for some
- Documentation is lacking, though they are making a real effort and started some really good guides
- Use things you are used to (JQuery, SASS...), no revolution
- Descriptive javascript is ugly, I'm sorry but I think it is
Cappuccino
To be fair, the first time I looked at Capp, I though: "Oh my god, they are doing something weird, what are they doing!" and I didn't try it. Then a friend of mine told me it was good. After thinking a bit I realized how idiot I was. The Capp approach is exactly what I would have done. I keep complaining that building an application is about logic and not about layout, design or UI functionalities. I mean, writing a drag and drop lib is not application programming.
I found the approach of: "Let's do something new" really refreshing, and I really like it so far. I might be biazed because of my long Obj-C history (I wrote a compiler, and implementation for Windows and some other esoteric things, that never left my computers).
Ok, that's for the jibberish, now the real review.
Capp approach is very different from SC. Basically, what Capp do is to remove the browser from the equation. Well, not entierly, but mostly. By removing I mean that when working with Capp, you will never encounter any web technology. By never I mean never. No html, no CSS, no DOM... Ok, if you tinker or really need to, you can blow the DOM, but you don't need that, even for very complicated applications. So, how does it work? Like a real application development framework.
When you develop with something like Cocoa (Capp use Cocoa as API model), you don't bother with the window server, you don't bother with how you will render your button, you don't bother with how your view will be displaced by 1pixel on some browser for some weird reason.
Capp approach is very simple, you don't target a browser, you build an application. For view rendering you have a drawRect method, exactly like a Cocoa application, in this drawRect method, go nuts with the core graphic functions to draw whatever you want. You heard me correctly, core graphics!!! Things like CGContextDrawImage works in Capp.
Then it's the framework job to render that app to a browser, not yours, can Capp is really good at that (except IE 7 and 8, but that's IE really slow JS engine fault).
Now Capp doesn't have a datastore, because an application framework doesn't. Capp only have Obj-J + AppKit. It is like Cocoa. Cocoa doesn't provide access to a database, CoreData is another framework, and if you want to use a PostgreSQL database, just do so. Capp is the same, you have Obj-C, an app architecture (with CPApp object and the like), but you can do whatever you want. There are tons of really nice addons for Capp which provides access to a databse.
Update: Cappuccino is in fact Objective-J itself, Foundation framework and AppKit framework. Objective-J and the Foundation framework can be used without a browser, using NodeJS for example
Honnestly, I haven't any Capp in production yet, so I cannot and I won't go any longer on Capp.
CoreGraphics
Update: I did not speak of CoreGraphics at first, and as it is a great feature, I will explain it a bit.
CoreGraphics is, as it names suggest, a graphic framework. It works in a very similar way of Quartz 2D.
It allows you to draw freely. For example, you want to draw a circle, with tradditional web techniques, you have to use a canvas, which requires boiler code to work correctly (like excanvas under IE), and the canvas API can be cumbersome. CoreGraphics API are context based for most of them, which means you draw within an abstract context that will render itself later on (for example, you can render to a PDF, a printer or in the Capp situation, a browser).
As a few lines of code are worth a thousand words, here is a small example that draws a line;
1 CGContextBeginPath(ctx);
2 CGContextMoveToPoint(ctx, 10, 10);
3 CGContextAddLineToPoint(ctx, 20, 20);
4 CGContextStrokePath(ctx);
As you can see, this is quite straightforward, of course, as it is context based, all those calls will be subject to the context is it called in, for the positions this is mostly the transformation matrix, and for the stroke call, this is the stroke color.
Now, in a browser, this is a very powerful and simple way to draw anything you need. I don't know exactly how much of the original Quartz API Capp implements, but the implementation is quite wide at the time of this writing.
Conclusion
Cappuccino is a real application framework, it's a really new and innovative approach to application development. The fact that it targets web browser is accessory, you are in a real application development environment with application centric problems and code.
Pro:
- Real and browser abstracted application development framework
- Really stable and mature (some widgets like the CPTableView are awesome)
- Obj-J makes things like myArray.each(function() {}) faster (read compilation), so Obj-J is fast, really fast
- Obj-J is cool
- The demo / real life projects are awesome, look at 280slides or github issues
- Nice community
- Update: CoreGraphics
Cons:
- You have to learn a completly new technology, I think it can be a Pro too, but I put it here for the skeptics
- Build tools and environment can be hard to install
- Slow under IE 7 and 8, but who uses that anyway? Update: this is easily fixable with the excelent chrome frame plugin.
Conclusion
While I might have been harsh on SC in this comparison, I use it in a couple of project in production and it works very well when mastered. It's a matter of knowing how the tool works. My main critic of SC is that the tool does not work as stated.
SC is now in a critical maturing process and is getting more and more attention, when the key components will be stable (like tableview or other widgets) it will be really usable without having to reimplement too much.
Being able to use CSS is itself a good thing because you can leverage your existing kownledge, but the price to pay is that sometimes the layout informations are split between javascript and CSS, which is in my opinion, a bad things.
Capp itself provides a more immersive developement experience, but it is clearly built and targeted at a specific kind of web application. Capp is good when you want an app in a window, with consistent behaviours. If you don't like the MacOSX interface, then Capp is not for you. If you want a 100% custom interface, SC is certainly a better choice. While Capp can render anything SC can, some things are just faster and easier to maintain in html+css for many people/companies.
Also, I'd like to note that SC and Capp are not the only projects out there for web applications. While Capp is, at my knowledge, the only one of its kind, there are other projects that provides bindings or datastore frameworks like SC do.