Structuring Large-Scale SproutCore Project Teams

written by pbergstr

Writing large desktop-like applications in SproutCore comes with a unique set of challenges that you wouldn’t encounter writing a smaller application. A smaller project with one or two contributors is a lot more flexible and requires less planning; a large project with many contributors and moving parts is a completely different beast.

I’ve worked on many SproutCore applications, both large and small, since 2007 and I’ve seen where a project can get into trouble when it grows larger both in scope and in team size. The goal of this post is to share some of my personal experience developing a large SproutCore application.

The Bliss of Smaller Projects

The benefits of smaller projects with one or two developers are relatively obvious. A small team makes it easy to stay on task for the limited scope of the project. Everyone knows what is going on because communication is easy and each developer has the opportunity to wear every hat in the project. Also, the developers working on the project know the code well throughout, mainly because two developers can transfer knowledge and be most effective if they are pair programming.

The Challenge: a Large Application

If you are given the task of creating a larger SproutCore application, such as a calendaring client, one or two developers cannot possibly deliver the application in the required time frame. In some cases, more than 100,000 lines of code may be required, much more than a small group of developers can manage.

In this case, the team must grow to a size where you can meet your timelines while not adding so many people that the project slows down. Since there is so much to do, you need to split up responsibilities; instead of having developers wear all the hats in the project, developers wear one or two hats, and act as the person the rest of the team can trust to deliver their specialized part of the code or functionality.

This is true of working in any large team; the goal of this post is to highlight the particular roles that need to be filled when creating a SproutCore project in particular. Imagine that your company, Initech, a typical software company, is tasked with creating a employee management application using SproutCore. The first aspect of the application, called TPS, is that a user can search for an employee and see employee’s contact information and location in the org chart. A user can navigate around the org chart using various methods such as list, tree, and grid views.

The second aspect of the application is of the management of employees; a manager can edit employee information as well as add and remove employees from their organizations.

What are the needed roles?

The roles that are needed vary from one SproutCore project to the next, and assigning them isn’t an exact science by any means. Over the past several projects that I’ve been involved with, as an individual contributor as well as lead, I have found that certain roles have benefitted the development effort the most. Let’s see how these roles map to the needs to the fictional TPS application by Initech.

How would Initech structure the team to create the SproutCore application? First, they would designate one of their most experienced SproutCore developers to be the technical lead/architect.

Technical Lead/Architect

In a large project, is it especially important to have a person who is an expert in SproutCore development and can act as the technical lead or architect. This person can start on the TPS project first; they will create the basic structure of the application in the forms of state charts and main view components as the rest of the team continues work on other projects.

As the technical lead, this person would have to figure out what different roles are needed for the project and also communicate that need to the stakeholders such as management, QA, system administrators, and designers. This person will still write code in addition to his or her management tasks, but most often their role will be to triage issues that the team needs help with.

The Data Modeler

The second developer that needs to be brought on is the person who will own the implementation of the data models, data source, and interface with the server. For a large project, this person will be fully engaged from the beginning to the end of a project. First, the developer needs to determine what the data model needs to be for the SproutCore-based application.

In the case of the TPS application, there needs to be several model objects such as Employee, Manager, Organization, and more. Once the model has been fleshed out, it’s the job of this developer to work on creating a client-server interface by creating a SproutCore data source; it’s also their role to work with the server team, if possible, to create a JSON specification that maps easily to SproutCore data model objects. This is crucial to ensure that data loads into the application quickly and without a significant amount of client side processing of the JSON before it is loaded into the data store.

Performance and Dev Tester

There needs to be a person that can own the integration testing of the SproutCore application; there also needs to be a person who can be dedicated to ensure that the application achieves the performance benchmarks laid out by the stakeholders. Performance is especially important when dealing with mobile applications. In the case of large projects, such as the TPS application, it is important that the various pieces that the different developers work on integrate correctly to create the overall product.

CSS, Spiriting, and Visual Stylist

On projects that are heavily design-focused, it is important to have a person that is designated to manage CSS styling and image spiriting. This person is in change of ensuring that the design vision of the project is correctly implemented. This person does not necessarily style the individual components that developers work on, but ensures that the global theme of the application is consistent and efficiently implemented.

As the individual developers work on their various application modules, they may style it inefficiently. It is the job of the CSS and visual styling person to go through and optimize as the project progresses.

Individual Module Contributors

The rest of the development team can be flexible and more fluid. Depending on the size of the application, you may need to have from one to five developers that contribute to different modules of the application.

In the case of the TPS application, you would have one or two developers creating the list, tree, and grid views as well as a group of two or three developers that can take care of the creation of different popup panels. Most of the popup panels in the TPS application will be things such as a preference panel, create/edit employee panel, create/edit organization panel, employee and/or organization inspector, and more.

The separation of the popup panels is important. More often than not, you do not want to load them up front and have them be lazily loaded as a module from the server. Therefore, it is vital to use a module loading scheme with a proper API to fetch and run the module as it is loaded from the server. You can have developers work on each of these, and if the API is correctly implemented in a loosely coupled manner, they can be replaced with an improved UI in the future without breaking the application.

SproutCore’s MVC structure comes in handy when allocating resources to each of these smaller modules; it allows people to work on different parts of an application without stepping on each other’s toes too much.

Also, if you have less experienced developers, making them start on a popup panel is a good way of giving them a limited starter project where they can learn SproutCore. If the code needs to be re-factored later, as long as the module API is properly implemented, it will not affect the rest of the application.

Conclusion

The largest takeaway from the projects that I’ve worked on is that you need to have a very strong developer work on the data model, data source, and client-server integration. If you don’t have that person, your project will run into trouble quite easily. When it comes to a SproutCore app, it is relatively straightforward to create the various user interface components, but without data flowing in and out of your application, all the hard work on the views do not matter at all.

While there isn’t a definitive answer as to how to structure a team of developers, this is the approach that has been the most successful for me in the past. Every project has different needs and it is important to take that in account when structuring the team. Also, it is important to take in account the talents and skills of the developers that will be working on the project.

It is important to give the developers the opportunity to pick what role interests them most and, if possible, put them in that role. For the most part, a happy developer is a productive developer.

Dispatch From The Edge: New Controls Built on Templates

written by gmoeck

The construction of the view layer has been greatly simplified by the new way of delegating the view’s rendering to templates. With templates, most things have gotten easier to do– particularly view rendering. However, there are a couple of benefits that the older ways of building views provide that became a bit more difficult within templates– namely, building controls. In this post, I’ll take you through the ways in which Templates have affected how we construct controls, and how to build yours as efficiently as possible.

Before templates, we had several drop-in objects that handled common controls. If I wanted to add a button to a view, all I had to do was something like this:

SC.View.extend({   
  button: SC.ButtonView.extend({     
   target: object,     
   action: 'something'   
  }) 
})

What was nice about this approach was that you didn’t have to worry about describing exactly how the button renders, or how it responds to things like mousedown or mouseup. This was convenient because generally all buttons have the same structure and code, and it let us work at a higher level of abstraction. If we were to do this inside of a new template structure, we would have to do something like the following:

views:

BaseView = SC.TemplateView.extend({   
        templateName: 'some_template' 
})

CheckAllView = SC.TemplateView.extend({   
    target: object,   
    action: 'something,   
    ...   
    mouseUp: function() {     
      ...
      this.get('target')[action]()
      ...
    }
    ...
 })

template:
<div class="something">
    ...   
    {{#view CheckAllView }}     

    {{/view}}   
    ...</div>

This makes it so that we’re essentially re-inventing the wheel every time we want to create a button view. It would be nice if we had some standard control objects, so that we could specify how to create a simple view hierarchy in the template.

Enter the new controls build on templates. Now, for example, using the new Button controller, you could do the following:

BaseView = SC.TemplateView.extend({
    templateName: 'some_template',
    buttonTarget: object,
    buttonAction: 'something'
 })
<div class="something">
    ...
    {{view SC.Button targetBinding=".partentView.buttonTarget", actionBinding=".parentView.buttonAction"}}
    ...</div>

These sort of controls now exist for buttons, text fields, and checkboxes.

So why not use the older view classes?

So why wouldn’t we just use the standard SC.ButtonView? Can we not embed those in our templates?

Of course you can do that; the only tricky thing is that some of the views are built to be positioned by the layout property, whereas many applications that are now using templates are not.

Furthermore, the actual code for the controls is implemented using templates, and so they are much cleaner. Look at the render method for the textfield view:

render: function(context, firstTime) {
      sc_super() ;
      var v, accessoryViewWidths, leftAdjustment, rightAdjustment;
     // always have at least an empty string
      v = this.get('fieldValue');
      if (SC.none(v)) v = '';
      v = String(v);

     // update layer classes always
      context.setClass('not-empty', v.length > 0);

     //addressing accessibility
      if(firstTime) { 
       context.attr('aria-multiline', this.get('isTextArea'));
       context.attr('aria-disabled', !this.get('isEnabled'));
      } 
     if(!SC.ok(this.get('value'))) {
        context.attr('aria-invalid', YES);
      }
     // If we have accessory views, we'll want to update the padding on the
     // hint to compensate for the width of the accessory view.  (It'd be nice
     // if we could add in the original padding, too, but there's no efficient
     // way to do that without first rendering the element somewhere on/off-
     // screen, and we don't want to take the performance hit.)     
     accessoryViewWidths = this._getAccessoryViewWidths() ;
     leftAdjustment  = accessoryViewWidths['left'] ;
     rightAdjustment = accessoryViewWidths['right'] ;

     if (leftAdjustment)  leftAdjustment  += 'px' ;
     if (rightAdjustment) rightAdjustment += 'px' ;

     this._renderField(context, firstTime, v, leftAdjustment, rightAdjustment) ;
      if(SC.browser.mozilla) this.invokeLast(this._applyFirefoxCursorFix);
    },

Versus the code to render the textfield in the new control:

defaultTemplate: function() {
    var type = this.get('type');
    return SC.Handlebars.compile('
<input type="%@" value="value"></input>'.fmt(type));
  }.property()

To me, this simplicity in and of itself is a win enough to use the new controls.

Until next time, this is Greg Moeck signing off.


Announcements:

We’re excited to welcome not one, but ** two new Meetup groups** to the family of SproutCore groups!

  • Los Angeles with their first Meetup Tuesday, June 7th

  • Provo, Utah Their inaugural meeting is in the works– stay tuned!

There are also meetups coming up in Chicago: Tuesday, 5/24, with a talk by Core Team member Tom Dale; and in San Francisco: Tuesday, 6/14, with a talk by Core Team member Colin Campbell.

In case you haven’t heard yet, there will be a SproutCore Bash on the first night of WWDC! Register here for drink tickets and the chance to win some cool giveaways, including an iPad2!

Hope to see you around! And, as always, let us know if there’s something you feel should be up here.

To Do: Build a SproutCore App

written by admin

In this 10-minute screencast, Tom Dale takes you from creating an empty SproutCore project to building a simple todos application. You’ll learn about defining model objects, crafting a user interface using HTML, then connecting them together with controllers. While doing so, Tom explains how thinking of your app in terms of its state, instead of how to respond to events, will change the way you build applications.

SproutCore 1.6 Beta Released

written by tdale

We’re excited to announce the release of SproutCore 1.6 Beta 1. As we mentioned in our last blog post, we are switching to a six-week release cycle, and this is the first release in that new plan.

Because we will be releasing more frequently, each release will be less of a big-bang release and more incremental improvements to what we had before. SproutCore 1.5 shipped with a number of new features, including TemplateView, and SproutCore 1.6 significantly improves the stability of TemplateView, TemplateCollectionView, and their integration with other parts of the system, especially DataStore.

If you are using SproutCore 1.5 today, you should upgrade to SproutCore 1.6 beta. It is essentially the same as SproutCore 1.5 with a large number of bugfixes and stability/efficiency improvements.

Changes

  • Bugfixes to synchronization between SproutCore RecordArray/ManyArray/ChildArray and TemplateCollectionView

  • Moved forms to experimental framework

  • Moved routing into its own framework

  • Improved ability to use table elements in Handlebars templates

  • CSS and cross-browser fixes for built-in controls

  • Significantly cleaned up in-line documentation

SproutCore and PhoneGap

written by ccampbell

Making sure your apps work everywhere is an important part of any mobile strategy. The mobile web allows you to reach your users wherever they are, and users have grown to expect that you’ll be there wherever they go.

Increasingly, users want to access applications through app stores; to reach your users, you have to be available to them as many ways as possible. PhoneGap allows you to put your web applications in a native wrapper and deliver them in the Apple App Store, Android Marketplace, and many other native app stores. It also integrates really well with SproutCore, making it the natural choice.

Getting Started

PhoneGap provides both JavaScript and native code. First, let’s deal with setting up the native side. For the purposes of this post, we’ll assume you’re setting up an iOS project. You can follow the Getting Started docs on PhoneGap’s website to get a running start.

Create your PhoneGap XCode project and save it right inside your SproutCore project’s directory (the one created with you ran sc-init). Let’s assume you’ve saved your PhoneGap project to ‘iphone/'.

Integrating PhoneGap with SproutCore Projects

The JavaScript code that comes with PhoneGap allows you to communicate with the Objective-C code (in the case of iOS) running on the native side. The best way to include this JavaScript API in your SproutCore application is to create a framework and then require it in your Buildfile. In your projects directory, run the following commands:

<code>mkdir -p frameworks/phonegap

cp ~/Documents/PhoneGapLib/javascripts/phonegap-uncompressed.js frameworks/phonegap</code>

Then, when editing your application’s Buildfile, require the PhoneGap framework you’ve just added:

<code> config :all, :required => [:sproutcore, :phonegap] </code>

The next time you build your app, the JavaScript you’ve included in your framework will be built with your project. 

Deploying

There’s a slight catch to be aware of when you go through this process: SproutCore’s build tools bundle your files assuming they’re going to run in an environment that supports absolute URLs (such as a web server). Since this is not the case in a native app, there needs to be an intermediate step to ensure your application will run when its in the PhoneGap project and on the phone.

There’s a Gist available to help with this. The script will build your application and replace instances of absolute URLs with relative ones, ensuring that your application will work on your target devices. It will also work for building and moving your app into multiple PhoneGap projects for different environments.

First, save that file to ‘build_phonegap.rb' in your project’s directory. Once you’ve got the file locally, it will be easier if you prepare a quick script (or integrate it into your build environment) instead of running it by hand all the time. You can create a file called ‘build_phone' with the following code:

<code>#!/usr/bin/env ruby

system('ruby build_phonegap.rb -a your_app_name -o ./iphone/www');
</code>

As you can see, this invokes the build script with the proper parameters. The ‘build_phonegap.rb' script will automatically run ‘sc-build' for you, as well as changing and moving the files into the specified output folder. The application name argument (-a) is the snake-cased version of your application (the same one as the folder name in apps/). From now on, when you want to build your application for use on the iPhone, you just need to run build_phone.

Note: if you can’t run ./build_iphone, you may need to make it executable. To do so, run ``chmod +x build_iphone.

Run

You can now follow the normal PhoneGap build procedures to run your app on your phone, deploy your application to the app store, and become an app rockstar with SproutCore.

Believe it or not, it’s that simple. SproutCore and PhoneGap combined make building an app-store-ready application a cinch. We’ll post more in the future about building and optimizing app-store-ready apps, so keep an eye out!