Archive for October, 2008

Cappuccino Tools: “bake”

Wednesday, October 29th, 2008

Note: please check the tools page on the wiki for the latest information on Cappuccino’s tools.

In the final installment of the Cappuccino Tool article series (for now), we cover “bake”, an automatic deployment tool. Writing a Cappuccino application does not require using “bake”, but can help with more advanced deployments.

Introduction

“bake” is somewhat analogous to Capistrano, a deployment tool often used for deploying Ruby on Rails and other applications, but “bake” has several features specifically for deploying Cappuccino applications.

The basic idea behind “bake” is to assemble a complete deployable copy of your application by pulling the pieces from various places (Git, Subversion, and local or remote directories via rsync), building it, packing it up, and deploying it to your server(s).

One key feature of bake is the management of multiple deployments over time, which allows three things: atomic deployments, keeping your client side code (the Cappuccino application) synchronized with your server side code, and enabling aggressive caching on all your static resources (code, images, etc). We’ll see later this is done by putting all the new resources in place, then “swinging” a single file, the index.html with a <base> tag.

“Atomic deployments” means that the deployment is updated to the new version in a single operation, which is either successful or not, nothing in between. Every client loading your application receives either the previous deployment, or the new deployment, but never a mixture of the two.

Keeping client code synchronized with server code is (sometimes) important for making sure users who have already loaded the application can continue using it even after you deploy a new version of the server side code that is incompatible with older versions of the client side code.

Aggressive caching of static resources reduces the load time of Cappuccino applications for repeat useres. This is possible because every resources URL is unique in each deployment, so we can set the “Expires” header far in the future (e.x. ‘Expires “Thu, 15 Apr 2010 20:00:00 GMT”‘). While the actual file name is not unique (for example Objective-J/Objective-J.js), in the deployed application the path will be unique (www.yourserver.com/YourApp/1225273279/Objective-J/Objective-J.js where the version number changes for each deployment)

Summary

The configuration for a bake deployment is specified in a “bakefile”, which is in the JSON format with a structure like the following:

{
	"sources" : [
	    {
	        "type"    : "git",
	        "path"    : "git://github.com/280north/cappuccino.git",
	        "parts"   : [
    	        {
    	            "src"       :   "Objective-J",
    	            "dst"       :   "Frameworks/Objective-J",
    	            "build"     :   "ant -DBuild=BUILD_PATH",
    	            "copyFrom"  :   "Release/Objective-J"
    	        },
	            {
    	            "src"       :   "Foundation",
    	            "dst"       :   "Frameworks/Foundation",
    	            "build"     :   "steam build -c Release -b BUILD_PATH",
    	            "copyFrom"  :   "Release/Foundation"
	            },
        	    {
    	            "src"       :   "AppKit",
    	            "dst"       :   "Frameworks/AppKit",
    	            "build"     :   "steam build -c Release -b BUILD_PATH",
    	            "copyFrom"  :   "Release/AppKit"
        	    }
	        ]
	    },
	    {
	        "type"    : "rsync",
	        "path"    : "/Users/username/projects/NewApplication",
	        "parts"   : [
	            {
    	            "src"       :   "",
    	            "dst"       :   "Blah"
	            }
	        ]
	    },
	    {
	        "type"    : "svn",
	        "path"    : "https://svn.youserver.com/Project/trunk",
	        "parts"   : [
	            {
    	            "src"       :   "subdirectory",
    	            "dst"       :   "Something"
	            }
	        ]
	    }
	],
	"deployments" : [
	    { "host" : "deploy@myserver.com", "path" : "/var/www/mysite/public" }
	],
	"templateVars" : {
        "APPLICATION_NAME" : "My Application",
        "BACKGROUND_COLOR" : "black",
        "TEXT_COLOR" : "black"
	}
}

This bakefile contains three “sources”: a git repository, a local directory, and a svn repository. The git repository is the main Cappuccino git repository, hosted on GitHub. You could replace this with a different branch if you needed a specific version, or even your own if you have one. This source contains three “parts”, Objective-J, AppKit, and Foundation. The “src” specifies where in the checkout the part is located, while “dst” specified where in the final built application it should be placed. You can optionally specify a “build” command, which is run from the specified “src” directory. This command should include the placeholder “BUILD_PATH”, which will be filled in by “bake” with the temporary directory where the build results are placed (equivalent to $STEAM_BUILD for any “steam” commands). Additionally, if you specify a “build” command you also need to specify a “copyFrom” parameter, which tells build the subdirectory of the build directory it should copy the built part from.

Once each piece of the application has been built it is copied to the appropriate subdirectory of a uniquely named (using the current Unix timestamp) “versioned” directory. Rather than deploying this versioned directory directly, it is placed within another directory which contains a special index.html file. This file includes a <base> tag that points to the versioned directory, which causes the browser to treat it as the base for all relative URLs, thus loading the correct version of all resources without requiring the application be located at a unique URL. “bake” will fill in “$VERSION” template variable in the base tag of the template with the correct

Additionally, “bake” will calculate the size of all code which needs to be loaded, in order to provide an accurate loading progress bar. The calculated size is inserted into the template variable “$FILES_TOTAL”. You can also specify other template variables such as “$APPLICATION_NAME”, “$BACKGROUND_COLOR”, and “$TEXT_COLOR” in the bakefile.

If you use your own template, the only required variable is the “$VERSION” one, but you can specify as many custom variables as you wish.

Finally, once the application has been built and assembled, it is optionally run through “press”, then gzipped. If the “–deploy” command line parameter was given then the gzipped application is transmitted to the deployment servers, un-gzipped, and copied to the deployment path using a specific sequence of command to ensure the deployment is atomic:

tar xzf 1225273279.tar.gz
mkdir -p /path/to/deployment
mv 1225273279/1225273279/ /path/to/deployment/1225273279
mv 1225273279/index.html path/to/deployment/index.html
rm "1225273279.tar.gz
rmdir 1225273279
cd /path/to/deployment
ln -nsf 1225273279 Current

(version “1225273279″, deplyoment directory “/path/to/deployment”)

One important thing to note about “bake” is that since the old deployment remains live (but hidden) if you deploy a fix for a security vulnerability you should manually purge all the old deployments from your server. If the change doesn’t introduce any incompatibilities between the server and client, you could set up a rewrite rule to direct all requests to the purged deployments to the latest, which is always symlinked to “Current”.

Conclusion

Once again I should stress that this tool is by no means required for writing a Cappuccino application. It was written to help deploy our production application, 280 Slides, but we have made it available for anyone who has similar deployment requirements. If it doesn’t quite fit your requirements, please feel free to suggest improvements, or even better, make improvements yourself and contribute them back!

Synthesizing Accessor Methods

Sunday, October 26th, 2008

Yesterday, Francisco and Tom checked in a new feature to the Cappuccino git repository, called accessor synthesizing. This is a new language feature for Objective-J, and its designed to reduce the amount of boilerplate code developers have to write in a custom class. Normally, when you write a custom class in Objective-J, you also write a pair of getter and setter methods for each instance variable (ivar) that you want to expose. This usually means writing repetitive code that hardly ever changes each time you write it. With accessor synthesizing, developers will only have to write getter and setter methods when something truly interesting needs to happen in those methods.

Accessor synthesizing adds a new keyword to the Objective-J language, @accessors. When declaring your list of ivars in the @implementation block of your class, adding this one keyword will tell the Objective-J preprocessor to implement accessors for you. Let’s see an example of a simple class written using the old method, and then the same class using @accessors.

This Person class has two ivars, firstname and lastname. Before @accessors, the class looks like this:


@implementation Person : CPObject
{
    CPString firstName;
    CPString lastName;
}

- (void)setFirstName:(CPString)aString
{
    firstName = aString;
}

- (CPString)firstName
{
    return firstName;
}

- (void)setLastName:(CPString)aString
{
    lastName = aString;
}

- (CPString)lastName
{
    return lastName;
}

@end

Using the new @accessors keyword, we can eliminate four methods:


@implementation Person : CPObject
{
    CPString firstName @accessors;
    CPString lastName @accessors;
}
@end

This second version is much more succinct than the first, and less tedious to program. We think this will be helpful for developers, and will increase productivity and code readability.

It’s important to note that this doesn’t change the way you use a class. For our Person class, in both cases, the code for getting the first and last names of a person (in the myPerson variable) would look something like this:


var fullName = [myPerson firstName] + " " + [myPerson lastName];

Similarly, setting an ivar looks like this:


[myPerson setFirstName:"Winston"];
[myPerson setLastName:"Smith"];

Like any key-value-coding compliant class, the name of the instance variable becomes the “property” or “key”, and that key name is used in the setter and getter methods. If your key is firstName, the getter for that key will be firstName, and the setter will be setFirstName:. The same pattern applies to any other key.

Configuration

There are a few configuration options when using the new @accessors technique. Perhaps most importantly, is the ability to change the name of the property. For example, if you declared an instance variable like this:


CPString _location @accessors;

Objective-J would generate two accessor methods called _location and _setLocation:. These are the expected accessor methods for a key called “_location”. In order to generate more friendly versions without the leading underscore, you can modify your declaration like this:


CPString _location @accessors(property=location);

The addition of the property=location tells Objective-J to use “location” as the new property name, instead of “_location”, which will generate location and setLocation: methods without the underscore. In addition, you can also specify the specific name of both the getter and the setter method, like this:


BOOL _hidden @accessors(getter=isHidden, setter=setIsHidden);

This code specified a boolean instance variable called _hidden; the getter method will be called isHidden and the setter method will be called setIsHidden:. One thing to keep in mind when specifying your own getter and setter method names is key-value-coding. Although we don’t yet have much documentation on the subject (you can read Apple’s documentation here), key-value-coding enables several important features in Cappuccino, so it’s important to maintain key-value-coding compliance. Normally, the rules are that for a given key, say “foo”, the getter is called foo, and the setter is called setFoo:. There’s an additional rule for boolean values, which says that you can use isFoo, and setIsFoo:, in addition to the usual method names. In our case, thats why our custom getter and setter names are still key-value-coding compliant.

There are two additional configuration options, readonly, and copy. By default, @accessors will generate both a getter and a setter. If you only want to expose a getter method to the world, you can add the readonly value in the arguments. The other option, copy, has to do with how the setter works. Normally, when you pass an object to a setter, it’s assigned directly. The generated setter looks like this:


- (void)setFoo:(id)aFoo
{
    foo = aFoo;
}

When you specify copy, the argument is first sent the message copy, and the return value of that message is assigned to the instance variable:


- (void)setFoo:(id)aFoo
{
    if (foo !== aFoo)
        foo = [aFoo copy];
}

This is useful if you want to ensure that an object you’re passing isn’t modified out from under you. Of course, it only applies to ivars that are both read and write, and cannot be combined with readonly. To summarize, you can use both of these options like this:


@implementation FooBar : CPObject
{
    id foo @accessors(readonly);
    id bar @accessors(copy);
}

History

Apple introduced properties in Objective-C 2.0, which added a new way to declare instance variables for your classes. The two key features were the ability to use what has become known as “the dot syntax” for accessing instance variables, and the second was the ability to have the compiler automatically generate accessor methods. Reducing code, especially code that doesn’t change every time you write it, is certainly a worthwhile goal, so we thought it would be a good idea to bring this new idea to Objective-J. There are a lot of things about the Objective-C 2.0 implementation of properties that don’t make sense for Objective-J, so we decided not to port them directly and instead developed a syntax that we believe makes the most sense.

The main goal we want to achieve is eliminating the need to write your own accessor methods. We don’t, however, support the “dot syntax” aspect of Objective-C 2.0. This makes the dual @property and @synthesize syntax of Objective-C 2.0 redundant. Furthermore, rather than just choose one or the other, we decided to use a new keyword, @accessors. This will lesson the confusion for existing Cocoa developers trying to learn Objective-J. It will also make sure we don’t have an incompatible syntax going forward, as we explore new ways to work with existing Objective-C code.

Conclusion

Accessor synthesizing will reduce the amount of boilerplate code that needs to be written, and make the language just a little bit easier to develop in. Overall, we think it’s a worthwhile addition to the language. If you have an opinion, we’d love to hear it, so sound off in the comments. Although this new syntax isn’t yet written in stone, we won’t expect to change it after version 0.6 of Cappuccino ships. Checkout the latest version of the git repository to start using this new feature.

We’re also considering other language features that might make it easier to program in Objective-J. If you’ve got an idea, or you’re interested in being part of the discussion, you should sign up for the mailing list, where we’ll be discussing some of the new proposals.

New Scrapbook Tutorial

Wednesday, October 22nd, 2008

We’ve just finished the latest installment in the Scrapbook Tutorial Series.  In Part II, we cover adding drag and drop to the application so that can begin allowing the user to start generating content.  In the process we cover a number of other Cappuccino topics, including creating and setting up collection views, panels, and scroll views.  We also briefly touch on the topic of serialization through Cappuccino’s keyed archiving API.  Make sure to check it out and give us your feedback!

Cappuccino Tools: “press”

Tuesday, October 21st, 2008

Note: please check the tools page on the wiki for the latest information on Cappuccino’s tools.

In the third installment of the build tools series we tackle one of the most advanced build tools: “press”. Recall from the overview that “press” is a tool for stripping code and other optimizations. Additionally, it can convert an entire Objective-J application into a single pure JavaScript file, which we’ll see can be useful.

press

The primary goal of “press” is to strip unused code from your application and frameworks and perform other optimizations. It needs to know about the entire application, including your application code and the Cappuccino frameworks, in order to determine the dependencies and remove unused files. It is called with two parameters, the path to your application, and the output directory:

press root_directory output_directory

This will run “press” on your application located at root_directory, and output a similar but smaller version (with unused files stripped) at output_directory.

Additionally, there are several useful options:

  • ‐‐main path: The relative path (from root_directory) to the main file (default: ‘main.j’)
  • ‐‐frameworks path: The relative path (from root_directory) to the frameworks directory (default: ‘Frameworks’)
  • ‐‐png: Run pngcrush on all PNGs (pngcrush must be installed!)
  • ‐‐flatten: Flatten all code into a single Application.js file and attempt to add script tag to index.html (useful for Adobe AIR and CDN deployment)
  • ‐‐nostrip: Don’t strip any files. Mostly useful for debugging.

‐‐flatten

The most interesting of these options is “‐‐flatten”, which converts your application into a single pure JavaScript file that can be imported with a standard “script” tag. While the Objective-J load system is great in most scenarios, there are currently a few limitations that a pure JavaScript file helps overcome. Namely that the load system doesn’t work in Adobe AIR due to strict security restrictions, and the load system doesn’t work across domains, such as with a CDN, also due to browser security restrictions. By flattening all Objective-J code into a JavaScript file, we can use a standard script tag to load our application, which works cross-domain and in Adobe AIR.

Internals

If you’re interested in how “press” works, read on. It starts by loading your application while noting which global variables are defined in each file. It then “walks” along the dependency “graph”, including every imported file, with one important exception: framework imports like “import <AppKit/AppKit.j>” and “import <Foundation/Foundation.j>” are ignored since these types of imports would result in the entire framework (including unused files) being imported. Instead, press looks at the global dependencies, and only keeps the files that are referenced by any other file that has been imported.

Conclusion

“press” is a already a great tool, but there is much room for improvement. In the future we would like to add finer-granularity code stripping, such as method-level rather than file-level. Additionally, we’re working on an automatic image spriting and optimization feature which determines exactly which images are required for your application and includes them in a single image, vastly reducing the number of HTTP requests to load your application.

Web Pages and Web Programs

Tuesday, October 21st, 2008

One of the best practices in modern web design is the concept of graceful degradation (or, if you prefer, progressive enhancement). The basic idea is that when a feature or section on your web page is not compatible with a particular browser, a simpler or alternate version should appear in its place. In other words, assume nothing will work, and then layer on additional functionality when its available. The same principle applies to users who have disabled Javascript; they should still get something that works.

This principle makes a lot of sense for web pages, but it breaks down when considering web programs. To understand why, we need to look at the difference between the two. Web pages are fundamentally about displaying information. The base interaction mechanism on a web page is the hyperlink, which links relevant pieces of information together and ultimately enabled “actions” to be taken on the user’s behalf.

What, then, is a web program? In contrast to a web page, a program is essentially a set of instructions to be executed by a computer. The most interesting programs (at least for our purposes) are the ones that run these instructions in response to a user’s action, e.g. clicking the mouse, or typing on the keyboard. The important bit is the ability to perform arbitrary commands, and for that we need a programming language.

In the computer science world, programming languages are generally talked about as being “turing complete”. At the most basic level, this principle means that although each programming language may work in its own way, they can all describe exactly the same set of programs — in fact, they can all express every task a machine can be instructed to perform. Languages that are not turing complete are not programming languages because they can only describe some (usually small) subset of possible tasks.

Why is this important? Because HTML and CSS, the languages of the web, or not turing complete. They can not be used to write programs. Javascript, on the other hand, is a full fledged programming language, and it’s the reason that web programs are possible.

We already decided that web pages should work when Javascript is turned off, but when it comes to web programs, is that even possible? After all, there are a limited number of things you can accomplish without the power of a programming language. Until recently, most applications targeting the web were built to run programs on a remote web-server, and then those programs were triggered when users visited a particular link.

This is a pretty good solution for a large set of problems, but it won’t work for all types of applications. Some programs won’t work with this traditional model, they need to run completely in the web browser. This means they cannot possibly work when Javascript is turned off. These are what I mean by web programs.

None of this is new information, nor is any of it controversial. It’s obvious that web programs have a fundamentally different set of requirements from web pages, and yet for some reason, developers are using the same set of tools to build both. This is one of the reasons we developed Cappuccino.

Cappuccino represents a significant shift in attitudes toward web application development. It was designed specifically and exclusively for writing web programs. None of Cappuccino will work in an environment without Javascript. After all, what use would a program like 280 Slides be without its interactive behavior? The program itself doesn’t have any data to display, so there is nothing to degrade to.

This design decision has encouraged us to make decisions that might otherwise be unwise. Most importantly, it lets us focus on the core problems of building a complex application, and ignore the problems of building a web page. From 10,000 feet, applications are mostly the same. With cappuccino, developers don’t need to work against a model that was designed for displaying static documents. Instead, they get to focus on the close up aspects of their particular application.

There’s no doubt that web pages are an important part of the web, and will continue to be so in the future. Similarly, the toolset that has been developed over the years around the problems of building a web page will continue to be useful. But thanks to increasingly powerful browser and pervasive broadband Internet access, web programs will be an increasingly important part of the web too. I sincerely hope that Cappuccino will play a role in advancing this new and exciting aspect of the web.

Cappuccino Tools: “objjc” and “steam”

Tuesday, October 14th, 2008

Note: please check the tools page on the wiki for the latest information on Cappuccino’s tools.

In our previous post on the Cappuccino build tools we summarized the purpose of four of the tools. In this article we’ll dive deeper into two of them, objjc and steam.

To review, the purpose of these tools is to prepare your application for deployment by pre-compiling all application Objective-J code into JavaScript, thereby reducing the load time for clients. Additionally, since most developers won’t need to modify Cappuccino itself, we always compile Cappuccino’s AppKit and Foundation frameworks to further reduce load time.

The only time you’ll need to run steam (which handles running objjc for you) is when you’re deploying your application, or if you’re making changes to the Cappuccino frameworks themselves. In the latter case, the easiest way to recompile the frameworks is to run the default ant task in the Cappuccino source tree:

cd /path/to/cappuccino
ant

To use the freshly built frameworks simply replace the “Frameworks” directory in your application with a symbolic link to the Release directory in the directory pointed to by your $STEAM_BUILD environment variable:

cd /path/to/your_application
mv Frameworks Frameworks-Original
ln -s $STEAM_BUILD/Release Frameworks

(if you’re loading your project through a webserver like Apache make sure to enable the FollowSymLinks option)

objjc

objjc, the Objective-J compiler, is the most important of the build tools, but you’ll likely never invoke it directly. objj can take any number of parameters as input filenames and output filenames (preceded by the “-o” flag). For example:

objj Class1.j -o Class1.o Class2.j -o Class2.o

This will invoke the Objective-J compiler (which is identical to the one used by Objective-J in the browser) on each input file, outputting JavaScript plus some metadata to each specified output file. Next we need to combine all of these individual output files into a single “.sj” archive that contains the JavaScript and import dependency metadata for the entire framework. It would be possible to do this by hand, but steam takes care of it for you.

steam

steam is the general Cappuccino build tool that manages the creation and compilation of your Cappuccino applications.

To create a basic Cappuccino application, simply run steam with the “create” command:

steam create ApplicationName

This will create a new Cappuccino application in the directory “ApplicationName”. This application can be modified and run (by opening index.html in the browser) without any further usage of the build tools.

When you’re ready to compile the application code for deployment, add a .steam file to your application, like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Name</key>
    <string>YourApplication</string>
  <key>Targets</key>
  <array>
        <dict>
            <key>Name</key>
            <string>YourApplication</string>
        </dict>
  </array>
    <key>Configurations</key>
  <array>
        <dict>
            <key>Name</key>
            <string>Debug</string>
            <key>Settings</key>
            <dict>
                <key>PREPROCESS</key>
                <true/>
                <key>FLAGS</key>
                <string>-DDEBUG</string>
            </dict>
        </dict>
        <dict>
            <key>Name</key>
            <string>Release</string>
            <key>Settings</key>
            <dict>
                <key>PREPROCESS</key>
                <true/>
                <key>PREINTERPRET</key>
                <true/>
            </dict>
        </dict>
  </array>
</dict>
</plist>

This file defines the targets and configurations for your project. This one defines a single target, YourApplication, and two configurations, Release and Debug. To compile your application, simply execute steam with the build command, the .steam filename, and the configuration name:

steam build -f MyApp.steam -c Release

If a .steam filename is not provided it will look for a file with the extension “.steam”. Likewise, if a configuration name is not provided, it will use the first one defined in the file. The following will run the “Debug” configuration in your .steam file:

steam build

steam gathers all “.j” files in your application, compiles them, and combines them into a single “.sj” file (“static Objective-J”), along with a new “Info.plist” which tell Objective-J which files are contained in the “.sj”.

The results are placed in a subdirectory of $STEAM_BUILD named the same as the configuration, i.e. Debug or Release. Alternatively, pass the “-b” flag and a build directory to specify where it should be built.

The compiled application or framework can then be used in place of the original uncompiled collection of .j files. If it was an application, copy or symlink your Frameworks directory to it’s directory. If it was a framework, copy it to your application’s Frameworks directory.

Conclusion

This article covered the core Cappuccino build tools, objjc and steam. Remember that you will probably never want to call objjc directly, but rather rely on the “steam build” command to manage the build process for you. Additionally, remember the build process is entirely optional (except if you’re editing the Cappuccino frameworks themselves), and is only necessary as a deploy-time optimization.

In subsequent articles we’ll cover the remaining more advanced build tools, press and bake, as well as further deployment optimizations.

Download

Cappuccino and Objective-J are licensed under the LGPL. For more information, see our licensing page.

Copyright © 2008-2011 - 280 North, Inc. Cappuccino and Objective-J are registered Trademarks of 280 North. Logo by Sofa. Hosting by Slicehost.