CloudBees Feature Management.io is an iOS SDK that allows developers to fix bugs and prevent catastrophes in production. It follows a simple flow:
Static code analysis checks how your application is built
Code is dynamically written (in precompilation stage) and acts as an adapter between SDK and your application.
Once the SDK is loaded it fetches the required hot patches and alters the application runtime on demand.
As some of this blog auditors mentioned, it is not a simple flow, we will ellborate more in a "CloudBees Feature Management.io - Under The Hood" post soon... Selecting a technology stack is no simple matter, you choose how much you'll bleed over it, what language you are going to write the code in, how your build process going to look, what IDE/text editors you're about to use, which services you'll be able to use and who you are going to hire. Inspired by Trello tech stack, we wanted to share the different parts of CloudBees Feature Management.io technology. This post describes what technologies we chose and why, we also supply our 2-cents based on the experience with various technologies. This post is correct for the time of it’s writing, we're always re-evaluating design and architectural decisions. So, lets dive inside:
Coffeescript
CoffeeScript is a little language that compiles into JavaScript, it is inspired by Ruby syntax but uses significant white space to delimit blocks of code. In previous JS project we had all JS files below 200 lines, in coffeescript
we reduced the limit to 75. For us, it is all about being clear and trying to forget the awful problems javascript has with “this” scoping. By the way, if you are using coffeescript, make sure you know about => vs ->. Pros:
Javascript, the good parts
@,->,=>, ?
Cons:
Debugging can be a bit hard (source map is not working well for me with requirejs). The good thing is that the transformation to coffeescript is pretty straight forward.
Need to be used wisely, don't overuse missing brackets.
I miss the ternary operator.
Bottom line: Code some javascript, and then abandon it in favor of coffeescript. it all about writing (and reading) less code.
Requirejs
RequireJS is a JavaScript file and module loader, it is the missing link for understanding and declaring how one JS file is dependent upon another (and other resources). When I implemented my first web application using elements, it just felt awkward: I was back to elementary school playing with cuisenaire rods
, and I didn't like it a bit. Requirejs is a asynchronous module loader, but it ain't about that, it is about the structure that it supplies and its wonderful r.js optimiser. We currently use require-cs (coffeescript plugin) and require-handlebars-plugin (for templating). Pros: Structure, optimizer, plugins. Cons: Some annoying boilerplate code is needed in every JS file Bottom line: The great thing about Javascript is that it is such a bad language that people created wonderful tools around it.
Backbone.js (+ Marionette.js):
Backbone.js is a non opinionated client side MV* (no controllers), it supplies structure to javascript client side application in the form of Models, Collections, Routers, Views and Events. It also takes care of model binding and server side syncing. Marionette.js is built upon Backbone.js, it adds a lot of missing components that you'll end up writing yourself if you choose to go solely on Backbone.js We didn't use angularjs because we don't have any experience with it. But, I'll tell you this: we really like backbone.js strategy. Once you get used to it you can reuse a lot of code for common practice relevant for your app. Although it requires the developer to do some work, most of it is removed with the use of Marionette.js (CompositeViews, onRender and serializeData functions, memory cleanup). If you are using Backbone.js, start replacing your backbone entities with Marionette.js equivalents - it will make your code much more robust memory wise, and you'll be able to do my favorite thing - delete code.
Go back to your backbone.js application and replace (almost) all your ".on" function calls to".listenTo" equivalent.
Sass (+Compass +Bootstrap):
Sass is CSS with superpowers, it is a language that compiles into CSS(similar to coffeescript over javascript). Compass is a framework built on top of Sass that supplies many tools and shortcuts that are required for ease of use and developer happiness Frontend development in the client side MVC world is a task for real software architects, it is not just about some form validation and cool animations. CSS is part of the frontend developer's work, and he deserves a better tool than CSS. CSS is all about repeating yourself all over and over again. Sass solves this with various techniques (@mixins, @extend, variables). Compass framework has many responsibilities: it complies the Sass files, creates sprites and css rules automatically (awesome!!!). As for Bootstrap (Sass porting), see the cons section. Pros:
DRY
Sprite generation
Already made @mixins for CSS3
Cons:
Takes too much time to compile (LESS is presumably much better), this is terrible
Bootstrap porting is based in class extending and not @mixin, which generates huge css files and takes ages to compile
Another layer of abstraction, harder to debug.
Bottom line: CSS for developers!
Node.js (+Expressjs)
Node.js is platform built on top of chrome's javascript runtime, it is event driven and asynchronous I/O model. Express.js is a lightweight web framework for node. So many was written in the last 2 years about node.js , that I don't have a lot to say. I think its maturity level for production debugging needs to improve, although I haven't done a lot of research on this matter, I am also a debug with logging kind of guy… :) As for asynchronous approach it is great for web server, fetching some asset, talking to DB and notifying EventEmitter that something happened. It is not suitable for simple script like tasks, we suffered from it in our previous venture when we had to compose a collage from a bunch of images. Express is a great tool, it does exactly what it should. REST api in a second with security enabled (via passport.js).
var heapdump = require('heapdump')
Mongodb
MongoDB is a document based database, it stores JSON objects (actually BSON) that can be indexed by any fields and can contain embedded documents. I was never that into relational DB, I always found it much easier to think in terms of object relations and not in terms of tables and joins. When the hype of NoSQL started we jumped on the train and (almost) never looked back. Why almost? When you are looking to hire someone that will deal with your DB if you choose an experienced DBA you'll be able to sleep like a baby, with mongodb, experienced DBAs are nowhere to be found.
(thanks @AdatoBoaz
) One server is like having none, make sure your application tolerates a DB machine crash (you need at least 3 machines to sleep good).
Nodeunit
Yet another test framework for node.js We write our code test first (TDD), we use nodeunit for unit testing and usually roll our own mocks. I am a fanatic TDD’er and it took me some time to realize that there are things not suitable for TDD, it can be too hard and not cost effective to test UI components with TDD. I recommend going over IsTddDead
(it’s not) but it should become a tool in your toolbox (my best one) instead of your religion.
Ruby
We didn't choose Ruby, some Xcode project reading and manipulation is needed in our SDK side, we chose to use the wonderful Xcodeproj library
(thanks CocoaPods) that is written in Ruby.
Objective C
Duh
libclang
clang (pronounced as klang) is a frontend for the LLVM compiler. It was created to replace GCC, which prevents its usage for commercial products. It is a great open tool that enables better IDE and better diagnostic tools for C, C++ and Objective-C. libclang is a library tool for C that supplies, among other, source code inspection. We are using libclang to read customers code and create the structure of your application. Anyone experienced with AST trees will recognize the syntax. Unfortunately, I wasn’t :)
Unit testing
When building an SDK you should test everything. We are using XCTest and we roll our own mocks for now. TDD in xcode environment is not like using jUnit, it takes too much time to run the tests on the simulator. Any advices? I haven't found a good code coverage tool around... Any thoughts? Waiting for your comments! We didn’t cover this in details but we also use services from amazon, google storage, loggly, intercom.io and some tools like npm, bower, grunt, etc.. As mentioned before, we'll talk about how all these things come together in our next post.