Taking Corona SDK to the Next Level

tl;dr; There is a larger opportunity in cross platform mobile application development that Corona SDK is missing out on. To solve this, Corona needs to invest in a version 3, mobile OS specific mobile component/widget set, C# compiling down to Lua, and invest in a proper, official IDE.

Introduction

If I were given a few million dollars to mold Corona SDK into what I believe it needs to become, here’s what I’d do. In order of priority I’d focus specifically on building a component library, making a more stringent roadmap for the current API in Lua, and continually improving the existing workflow. All 3 will help increase Corona’s uptake by developers who specifically target “mobile first”, increase desire by those working in agencies who wish to have a quick way to target multiple device OS’, and most importantly broaden Corona’s ability to quickly iterate on mobile applications vs. the existing game focus.

Why Components?

The existing widget library is too small to fully encompass the needs of serious mobile application developers. Much of the onus is put on developers to build both Android and iOS components, from scratch. For B2B clients, this reduces the capability of those pitching a quick cross device solution as much of the initial Time & Materials contract must be devoted to building a component library that’s iterated upon while developing the application. This also makes time estimations in a Fixed Bid challenging because you’re basically coding components YAGNI style and too much risk is placed on accurate developer time estimations for component development that the client hasn’t seen yet. At this point, going native is more attractive because they already have these components, and then your only concerns are what devices are you targeting and what is the minimum OS version.

For product companies, this also provides a number of problems. For those wishing to offload as much work to the platform as possible, they can’t. Google builds Android components, Apple builds iOS components, and 3rd parties fill the specialized gaps. For Corona, all 3 must be solely owned by the actual company developing the product. This is a significant amount of time spent by the product company building the necessary tools to build their product vs. just building their product. For those looking for the quick pitch of their product via a paltry prototype, this lessens their desire/quick ability to do so.

The long term projections are worse since Google and Apple will be around awhile to support legacy components whereas for smaller companies, this maintenance burden is on them, some of which they cannot support without taking already strapped resources away from mission critical projects. Finding 3rd party contractors is also harder for a specialized tech with a specialized implementation.

Why use Corona to build mobile applications when you get iOS components for free and Android components for free, both with native speed, and professional tooling?

Why use Corona to build mobile applications when you could just use Twitter Bootstrap/jQuery mobile/Sencha Touch + PhoneGap and still retain a modicum of code re-use for the mobile website, and desktop website?

The key here is “speed”. A reasonable sized component library plays a critical role in ensuring that speed is a reality for service companies targeting B2B companies and Agencies bundling mobile applications alongside additional offerings.

Why Lua API improvements?

A consistent API is directly proportional to the learning curve, developer trust, and scalable growth of an SDK. If the API remains consistent, developers can learn new functionality with less effort. This includes existing functionality and new functionality added later. A lot of developers have trust issues with code they didn’t write, and for good reason. A consistent API makes it look well thought out, and a developer is more apt to build in the style on top of the API if its consistent. Finally, if you’ve built the API in such a way that the style allows new, and different, functionality to be added, you lessen the burden on your developers, and yourself.

Corona currently is about 60% there. That’s more than good enough, but I think they can do a lot better.

Why Workflow?

Even the creator of Doom recognizes the extreme value of Corona’s insanely fast, simple, and iterative based workflow. However, it’s not 100% cohesive, especially when you bring Enterprise into the mix and dealing with both multiple devices and multiple OS’ through multiple code bases with a variety of build systems.

This is where “the death of a thousand cuts” can be turned into “it’s all the little things that count”. Nothing huge here, just a plethora of small improvements to make the whole better.

Widgets, Components v3, and v4

Corona already has a version 2 widget library. It’s on Github and you can add and fork to your hearts content. Part of the value was Corona Labs owned it, they provided the API direction, they “ate their own dog food” to help influence how the core Corona API would satisfy components, and this in turned helped dictate how their users built apps. There were 3 main problems.

First, the components aren’t thorough enough. To build applications, we need a true library of components; lots of them that allow us to easily satisfy the Android and iOS Human User Experience Guidelines. While the B2B’s do not give a flip about the user, this can sometimes be life or death for the product companies. Additionally, building components either specific to a device OS or x-device are a time consuming endeavor. With a YAGNI focus, this makes it challenging to re-use across projects for the B2B’s. As previously mentioned, this also puts the development & QA burden on the product companies.

Second, the v2 widgets are still being tested. We’ve all found minor bugs both visual and functional, and this is fine & normal, but they need to be tight not just on the device, but on the simulator as well. The Mac vs. Windows simulators being different is a burden on developers. The engineering effort involved on just the simulators alone must not be overlooked. Flash and HTML got a free ticket because the runtime engines were similar on device and desktop whereas native solutions have to build it themselves. Google and Apple have epic resources compared to Corona Labs. I get devoting resources here isn’t something to take lightly, but when developers spend 60% of their day coding, 10% testing on actual devices, the other 30% is viewing/testing things in the simulator. Putting the burden of compensating for different functionality between Mac vs. PC may seem more prudent because it’s faster to iterate/compensate in Lua vs. native code… but that doesn’t work long term.

Third, the widgets are beholden to the current Corona API. There are a ton of lifecycle events and base classes needed to truly build an effective, abstracted component library for developers. Corona currently doesn’t have them. That is why I’ve broken out the Component Roadmap into 2 phases; same API, but different internals. One for the current implementation as Corona stands today, and 1 based on future API’s which I outline in more detail in the Lua improvements section. The v4 component lifecycle is not included in this epic post, but if you combine ECMA 6 proposals, non-IE event models, and as simple as possible component API’s that include Model support, you get what you’ll need lifecycle event wise which Corona currently doesn’t have.

Widgets v3

The current widget v2 library is good. We need a thorough v3 written from the ground up  that supports:

  1. a common API
  2. built-in collections/models
  3. a common event model
  4. built-in & abstracted invalidation
  5. a networking/RPC wrapper
  6. a thorough set of visual GUI components, x-device
  7. a simple styling model, whether CSS or code based
  8. a set of utility functions for common GUI development (events, collection decoration, field validation, formatters, etc.), some of which will go away as native equivalents are created in the future
  9. a concerted effort to build specifically for the OS vs. 1 component that adapts to the OS
  10. a built-in MVC framework
  11. unit & functional tests framework

I personally don’t feel v3 should be open sourced as this causes unnecessary overhead initially. Later when it’s mature and v4 is on the horizon, sure. The actual source code itself, however, yes, should be accessible for developers to debug, learn, and extend.

It’s assumed the components will be coded in the Lua 5.2 module syntax which is backwards compatible with 5.1. It’s also assumed as much abstraction as possible is done internally to ensure any native API’s are seamlessly integrated in the future (i.e. Scale 9, built-in invalidation, etc).

Finally, there needs to be a white paper describing component code best practices that confidently asserts this is Corona’s suggested way of coding. That sends a message and helps mildly coral the developer populace.

v3 Common API

This entails a standard way of engaging with Corona SDK components in that they all follow the same standards and conventions. These are documented in the white paper.

To utilize a component, you follow the Lua 5.2 module syntax:

local WidgetClass = require "widgetsv3.WidgetClass"
local instance = WidgetClass:new()

The high-level conventions include setter methods and getter properties. Given the existing way of building classes & modules in Corona without 3rd party library dependencies means you’re using either closures or metatables. I take a hardline stance against metatables. It makes the code harder to read & follow, and is unnecessarily verbose for little gain.

Thus, the way to get properties is like so:

-- get the value
local theLabel = instance.label

-- set the value
local theAge = 21
theLabel = "Age: " .. tostring(theAge)
instance:setLabel(theLabel)

Notice we follow dot syntax for getting, and colon syntax for setting to ensure scope is retained.

v3 Collections

To support Collections, Array’s that support filtering, sorting, and change events congruent with the Observer pattern, any component which supports Collections also supports the same get/set syntax:

local Collection = require "widgetv3.model.Collection"
local List = require "widgetv3.view.List"
local people = Collection:new()
local myList = myList:setCollection(people)
local myListCollection = myList.collection

The point here is people:addItem(somePersonVO) will automatically update the List view. Which leads to…

v3 Event Model

The existing event implementation in Corona and associated widgets are great. However, there are 4 main issues that need to be addressed in v3. These are:

  1. adding event dispatching capabilities to tables that aren’t Display Objects (addEventListener vs. onSomeCallback=someFunction)
  2. following a strict syntax model to add consistency to the too-flexible Lua
  3. supporting a built-in event bubbling for Display Object non-native events
  4. a common set of events for the built-in common ones typically used to ensure a consistent API

For non-Display Objects, that’s easy (sort of), already have a class for it. This ensures the same API both for v3 and v4 when this is implemented natively.

For a strict syntax, basically to listen for events:

myList:addEventListener("itemTouched", myListener)

While the function as the listener is a valid 2nd argument, most will be tables if you follow the white paper suggestions on coding syntax. No more listener in the constructor like v2:

local tableView = widget.newTableView
{
    top = 100,
    width = 320, 
    height = 366,
    maskFile = "assets/mask-320x366.png",
    listener = tableViewListener,
    onRowRender = onRowRender,
    onRowTouch = onRowTouch,
}

Instead, you’d simply listen for it:

tableView:addEventListener("onRowRender", myListener)

This includes event naming; v3 would use “rowRender” vs. “onRowRender”. This would be consistent upon all events, both native and component based.

The same goes for “callback” style events such as transition.to which allows you to pass a callback function/table for each tween instance (*ahem*… “id”, not instance) that is returned. That kind of functionality/syntax is gone. Instead, again, you go:

myTween:addEventListener("onComplete", myListener)

You’ll notice, currently, transition does not support that kind of API, nor does transition return specific tween instances. Instead, it manages those internally and merely exposes numerical ID’s with which you can optionally track your own tweens and cancel them. This is where part of the component layer needs to abstract the existing Lua API, both for ease of use, and hope that when some of the native Lua API changes take place, the component API will remain the same but the performance will improve.

The network.setStatusListener has the same syntax to allow a terse, easy way to quickly verify multiple URL’s are reachable. The new syntax would, again, follow the standard:

local myListener = function(event)
   print("reachable:", event.isReachable)
end
network.addEventListener("networkStatus", myListener)

This, also again, helps prevent yet another way to add and remove event listeners.

Another example includes Scale 9 and Scale 3 graphics, where you cut up a button’s image into 9 parts so it can scale vertically and horizontally while still looking nice. There is currently a significant amount of overhead having Lua do this vs. having it handled natively. If you keep the API & workflow the same, the v4 transition for those who wish to update their applications should be seamless… or at least not very painful.

Event bubbling already takes place for many Corona events including tap, touch, and collisions. In fact, it’s actually up to the developer to stop propagation on purpose both for tap/touch visual hierarchy and for collision propagation amongst physics objects. However, there are 2 problems when the developer wishes to do this themselves.

First, they have to manually bubble their own custom events, even if dispatched form a display object class. Second, they have to target re-acquisition as to what stage in the bubbling process the event is.

Frankly I don’t care about this 2nd part, but it doesn’t really follow the ECMA standard for event bubbling. Yes, I get I buried a reference to the ECMA Script standard in here… we’ll get to that more later as using ECMA 6 as a possible v4 language implementation vs. C# compiling down to Lua… which if you know anything about C# has its own event model way of doing things. The point is, the framework, currently, has the emulate it until the native API can handle it or offer an alternative.

Finally, standard events need to be implemented for all components to provide a common API. For example, when a component is shown and hidden, when it’s created for the first time and when it’s about to be destroyed. These lifecycle events are crucial for larger components together used via composition. This also includes “touch”, “change”, etc.

v3 Invalidation

I’ve talked a lot about invalidation in the past, but for those of you who are new to the concept, I’ll explain a bit about how it works and how it affects the current suggested implementation for v3 in Lua.

First, Corona for the most part draws one time per frame. This means if you do this:

myCircle.y = 100
myCircle.y = 200
myCircle.y = 300

You will ONLY see the circle appear at a y position of 300. This is because Corona draws once per frame, based on the current frame rate of your application (which is either 30 or 60). That means, at most, you can draw 30 to 60 times a second.

This is both an optimization and feature; Corona takes the “latest” transformed visual properties if any, and draws them to the screen. That is an INSANELY complex process boiled down into 1 sentence. That’s great Corona does this. They may do some of their own invalidation internally to handle code like the above.

However, components often do more complex drawing than merely moving itself via changing its x and y properties. A button will change a text label, a list control will redraw a row, or a for could show/hide a section of content based on the current state of the data the user is editing. These changes will propagate; meaning the form will move a container which in turn does additional layout to item holding the label and text input, which in turn re-measures it’s internals based on abstracting native text fields which do not exist in Corona groups… etc.

As you can see, on larger applications, it is critical to ensure we don’t run a bunch of moving, sizing, measuring, or redraw code more than once per frame, else it’s pointless. When you have 3 components, fine. When you have 60, each running 3 complicated layout/redraw routines when only the last one is actually shown… this is a performance problem AND an API design one. There are rare cases where you need to force a redraw for measurement purposes, and that’s fine.

Invalidation fixes that. Or at least, lessens the damage from a scalability perspective.

There’s two more things invalidation helps, and those are race conditions and order of operation errors. I lumped them together because for GUI components they’re often related.

For example, a List control (another name for a TableView), could have 2 properties you could set that affect how the list draws, the collection and rowCount (how many rows are shown/drawn). Assuming you know how a list works, you go:

myList:setCollection(myBigOleCollection)
myList:setRowCount(4)

Now, internally, you’d think the list would first setup itself in its internal constructor, draw the list contents upon getting the collection set, and finally redrawing or masking itself to respect the new rowCount value.

…but what if you went:

myList:setRowCount(4)
myList:setCollection(myBigOleCollection)

Without invalidation, that’d either fail, or run some complicated internal code that wouldn’t scale well.

With invalidation, it’d run, and scale well.

Invalidation basically sets data immediately, but doesn’t actually draw it till 1 frame later.

For now, invalidation would follow the standard that Flash and Flex followed:

  1. “properties” are defined as getter/setter methods. They set an internal property with the same name prefixed with an underscore.
  2. They also set a dirty flag to true and call “invalidateProperties”
  3. invalidateProperties adds a listener for enterFrame.
  4. 1 frame later, the listener is removed, and commitProperties is run.
  5. commitProperties checks for all dirty flags set to true and applies them in the order the developer sees fit.
  6. If a dirty flag is already set to true, calling a setter again merely updates the value, it doesn’t actually affect redraw unless the developer wishes to override this behavior.

Using enterFrame ensures we only ever call commitProperties once per frame, and thus all components only ever draw once per frame unless the developer specifically needs to for measurement purposes. In turn, these changes can propagate into child components ensuring composition redraw works as intended.

This gets really complicated with GPU acceleration and the Container class’s built-in masking abilities, so as far as v3 is concerned, it’s suggested the developer will do as little composition as possible with regards to massive/frequent redraw.

Invalidation is only for GUI based controls.

I’ve included 2 Gist files that show the base Component class without any size invalidation (width and height + Container masking + measurement abstraction go beyond the scope of this article) and a TextField wrapper called AutoSizeText that uses component (the lack of text field object pooling also goes beyond the scope of this article, just focus on setText for now).

RPC Library

The networking 2.0 library is great and retains the same API as v1. However, even with such a high level abstraction, it is still pretty simple in terms of supporting common code written by client developers hitting REST based web services. Developers working rest back ends expect something at LEAST along the lines of what AmplifyJS or jQuery or even the Flex SDK offers with regards to a remote procedure call library. Borrowing ideas from iOS CoreData, Flex SDK, and Backbone’s Model internals helps give you some idea of the common things developer need to handle.

This includes:

  • encoders for common request serialization into JSON, XML, and normal REST in addition to the existing text & binary support (automatically parse Lua tables to the correct format for sending over the wire)
  • decoders for common response deserialization from JSON, XML, REST, and plain text in addition to the existing text & binary support (automatically parse from text/binary to Lua tables what was sent over the wire)
  • custom error handling around the decoders that adds to the existing handling of event.isError and timeout
  • concurrency configuration support around the existing networkId: multiple, first, and last. (ex: if set to last, and you make 5 http requests on the same service, the first 4 will be cancelled).
  • a common “result” and “error” events vs. 1 which the developer is required to sort through. These are dispatched from a particular operation instance unless the developer uses the default RestService.

This is not a small under-taking, but is pretty much the back-bone of any application which hits more than a few REST web services, even in a read-only fashion.

Additional Widgets

The Widgets v2 library had a philosophy about core, useful components that allow developers to use them for the more complicated components per device OS, and the rest they can build themselves.

v3 takes the stance of giving the developer zero reason to build device os components from scratch. Instead, they should be focusing on composition; ie, “building their application”. To optimize development, this also means no more flexible “1 size fits all” components. This also means the components will not just have to be divvied up by device os, but by type and market such as Table vs. Phone, Kindle vs. Nexus 7, etc. The process here needs to be pretty iterative to help determine the components being built are relevant for those projects not just being built, but “pitched”. Remember, larger clients say they care about design, but they don’t; at the end of the day, standard looking components supplied by Corona are good enough.

This last part is important for 2 reasons. Having mid to junior developers capable of mocking up workable “prototypes” for sales teams to help sell their ideas quickly leads to the “prototype is the product” problem for developers. Say what you want, but the sales team DID get the sale because of that. This in turn helps drive Corona as a repeatable platform for sales & development.

The second reason is that those developers building custom components have the opportunity to contribute back. Again, I don’t feel open sourcing v3 is prudent, nor do I believe Corona Labs has the resources to manage such an endeavor. The point here is providing the core component API’s for those developers to follow so they can at best offer it as a pull request in the Github repo, or at least blog about it and others CAN use it within their Corona projects and have that code play nicely with the standard stuff.

The existing v2 skinning framework was great, but to help lessen the measurement/layout burden on the component developers at Corona, it should be coded for the specific OS they’re targeting.

SOME form of styling needs to be implemented. I don’t like using CSS either when skinning suffices for 90% of non-agency projects, but for those developers who just want font, icon, and color changes you can’t beat the speed & usefulness of CSS based styling. Yes, I realize this adds a significant amount of work, but again, we’re targeting momentum of the platform here in v3 to help garner feedback, enablement is a priority. Targeting is a gerund, why the heck does it have just 1 t?

Utilities

No component framework is complete without a suite of utilities. This includes formatters, validators (which can be used in the GUI layer as well as the Model one), externalized caching & local storage. While most are abstracted away in their respective layer (like validators), it is still prudent to expose these for the developer for a few reasons, namely their productivity, custom integration, and easier for Corona Labs to integrate into the components if they design the actual API.

These are also the opportune area to take a lead role in abstracting away POTENTIAL (yes, potential, not ensured) future features. For example, abstracting away 9 scale and 3 scale graphics makes it easier to port and/or learn future API’s when it’s made native. Same goes for Bitwise operators, certain API’s that’ll turn into native plugins, and a variety of API’s I’d personally have to organize some of the disparate device querying API’s like system vs. native.

Built in MVC

If you want to create an experimental application framework for the sake of learning how, what, and why users are building with your tech with room to pivot/iterate later one, you release a component set. If you already know and just want them to succeed on larger endeavors, you do the same but include an MVC framework along side it. There are pro’s and con’s to each approach.

The cons to the component-only approach are people don’t take it seriously for larger scale development, it’s harder to sell to potential clients who have ornery W2 space cadet architects at some larger enterprise, and you tend to attract less B2B clients. This last point is because most service companies let their clients usually dictate the tech. The pro’s, however, are you get a lot of flexibility to setting your next direction. Users always surprise you, and component directions can be widely different on your next iteration (somewhat like Widgets v1 and v2 are now). Additionally, you have a quicker time to market since you’re just focusing on a set of widgets, each delivered on a particular milestone release. You don’t have to release them all at once. Finally, those tinkerers you do attract the are the most likely to give you valuable feedback and experiment a lot with your tech.

The cons to the bundling of an MVC framework with associated classes is you’ll have a smaller market at first using it. These are typically a specific demographic, those building larger applications for media companies, but more usually banks, healthcare, and insurance. You also have to have a TON more man power for an initiative that doesn’t include engineers. You have to include a sales person alongside a sales engineer. At first they can handle a few clients, but eventually, they’ll be spending most of their time with 1 or 2. You’ll then need some consultants to help implementation prototypes or help an existing team solve initial development challenges. They’ll usually be one unit with the 2 sales reps… next thing you know you have 3 such teams, each consisting of 4 people. This is not a scalable business model for a product company and yet it’s integral to get to that milestone of tech validity.

The other con is you exclude a segment of your market place who don’t “get it”. I feel like Sencha has done a really good job here; you’ll have some of their users using a few components while others adopt the entire stack. The challenge to solve is how you market it, and how your evangelists balance those 2 demographics in their engagement.

Finally, the other con is time to market is significantly slowed. Everything is integrated and needs supporting classes. It’s a ton of code some of which may be temporary so you really need to spend the time architecting it right, iterating, and getting a close knit set of private alpha testers to provide feedback.

The pro’s, and hence the part of the point of this article, is that people can build scaleable applications on your tech right out of the gate and the larger companies take it seriously. The other pro is, you’ll start attracting those who don’t agree with your MVC philosophy  or they do, but it’s not good for their consulting business, so they build their own MVC framework. Both of these help validate your tech in the market place, as well as help sell it.

I have one I’ve started, but naturally I’d prefer if Corona did some market research to determine where on the MVC spectrum their customers lay so one could be built specifically for that market segment right out of the gate and let 3rd parties do their own flavors on top/alongside.

Unit and Functional Tests

I’ve read that Corona has their own unit testing suite internally, which is great. For components, however, it needs to be public for a few reasons. First, so architects take it seriously. Second, for those who build/extend/modify the framework into their own Continuous Integration environments. Third, for the opportunity that the community can potentially find and fix missing/broken tests and add relevant ones as well as keep the existing ones up to date.

I don’t believe functional testing is required, BUT it would be a huge precedent in a later milestone release. Some of the larger automated testing tools like SmartBear, QT, and others that could integrate with the framework. You have to build this testability into the framework, more so than just making it unit testable. It’s a huge endeavor.

Component Conclusions

That handles the introductory component plan. Remember, v3 is an iteration on the existing Widget v2, but with a specific OS focus. The v4 is simply an iteration on top of v3’s foundation to provide a stepping stone for those developer evangelists in v3 to showcase v4. V4 runs atop the Lua and Workflow improvements mentioned below. The hope is the philosophy will be the same, as the API, but taking full advantage of improved native and Lua API’s to provide a more robust component framework. There isn’t really a need to cover v4 in detail because once you get v3, and see where Lua should go, you’ll see v4 is just a component framework with built in MVC on top of an improved/iterated Corona platform.

Why V4: To compete with native implementations from a cost perspective.

Isn’t that what Corona already provides? Not for larger application development, no.

Lua Improvements

There 2 main Lua improvements that have to happen in order for v3 to take off, for a good designer/developer workflow to flourish, and for a v4 to even happen. These are:

  1. API consistency
  2. More robust programming language

Without these, you’ll have continued slow growth, and lack of serious community investment to more serious application development atop Corona.

API Consistency

For the current incarnation of Lua, whether this is 5.1 or 5.2, many of the API consistency issues I’ve already mentioned above such as event syntax, but other things like a display.newLine’s stroke width using the “width” property whereas a display.newRect’s stroke width being a strokeWidth property.

The Corona team needs to take a breather, and do an architectural review from an API consistency perspective on their current SDK. Next, they need to publish these naming rules for those building atop it in the form of a white paper. This includes their native plugins. This can simply be a dot release, such as 2.1.

Lua’s actually worse than JavaScript with regards to “everyone doing their own thing”, which is remedied by taking a stand and dictating the standards.

Another Language?

The battle for robust vs. light, strong-typing vs. variant, etc. will continue to rage. Regardless of your opinions and inferences, the facts are those building applications in the Enterprise use robust languages to do so. While many use Python and Ruby and PHP just fine, if you want the guys who make the big money to invest in building mobile applications atop Corona SDK, and thus justifying to investors while you’re spending tons of your money on this break from the gaming philosophy that has primarily driven Corona SDK so far, you need some quarterly profits to show. You get those profits by providing an SDK people will actually use.

For those company demographics, Lua is not the gateway language to use. That’s Java, or even C#.

Reflection and Dependency Injection

A short note on reflection API’s. Right now, Lua’s support for language metadata is pretty horrible. Even if you stick with Lua 5.1, attempting to do runtime Dependency Injection is pretty miserable. The package API’s were some kind of attempt that seems… unfinished? 5.2 doesn’t make it any better. You basically have to find a lexical parser to do runtime parsing of classes at runtime to handle the injection of dependencies with some convention on constructors. I only bring this up because if you say, “Of COURSE our platform supports Inversion of Control!”, you immediately set a lot of Enterprise Java devs mind at ease.

Interpreter Challenges

Beyond the obvious advantage of Lua’s ease of integration with a variety of hardware and native code which forms the crux of Corona SDK’s value for mobile, you can’t easily just swap that out with another language.

You have 2 options here. The first is to bite the bullet, and pick one that provides a long term gain, such as Unity did with C#. The problem with Java & Objective C is that segments a market. You imply you can “build cross platform apps using Objective C vs. just 1”, but that masks really what Corona does, both good and bad. So those 2 languages are out. While C# certainly appeals to the gaming & Microsoft crowd, the Microsoft realm already has mobile solutions with their existing platforms, with a heavy Windows Phone bent.

The other option is create or use existing cross compilers so developers can use more robust languages, but still compile to Lua in the background. This significantly lessens the engineering effort, but increases the communication & leadership requirements around the workflow initiative. Someone has to keep in sync the tooling, the existing SDK features, all the while trying to drive the language philosophy IN FRONT OF those initiatives vs. behind. Rails was built on TOP OF Ruby, just like Django; those frameworks espouse the good in those languages. Without the language being fully baked, you have a starting timeline problem even on Day 1.

Worse, it could be incremental. Examples of those are TypeScript, CoffeeScript, ActionScript 2. ActionScript 2 was created in response to ActionScript 1 not being application developer friendly enough. It fixed a few things in the ECMA Script based language, notably JavaScript’s lack of super, but at the end of the day, still compiled down to a JavaScript ‘esque prototype based language. All compile time checking was runtime based, all classes, like TypeScript does as well, compiled to prototype based implementations for performance reasons (vs. closures), and all packages were name space based. AS2 effectively “bought” time for Macromedia to make ActionScript 3, the ideal (at the time anyway, before Haxe) ECMAScript 6 (known as 4 at the time, heh) based language. This satisfied those ornery, OOP craving Java Developers.

CoffeeScript sought to solve the lack of proper package, class, and built-in scope support for JavaScript. The lack of strong-typing and tooling really makes CoffeeScript less than ideal for those wishing for more support.

…which is what TypeScript satisfies AS WELL AS making ECMA Script 6 easier to use, today, vs. using Google’s Tracer compiler. The problem with TypeScript is that, currently, the only tooling support of significance is in (surprise surprise) Visual Studio.

All of those languages open up problems with “why not just code native JavaScript?”. It’s a good point. Many large scale Sencha applications (most behind a firewall, lulz) are proof you CAN develop large scale, client-side applications, but the point here is SHOULD you? I mention client side since technically, for GUI reasons, client side code can be quite verbose to API style server-side offerings. If your code base is large, and science shows less lines of code is better, what is the happy medium?

Lua already cross compiles, but lacks the OOP constructs we need. No, Lua 5.2’s de-facto module approach is not enough.

One strategy could be have C# compile to Lua, another could be to just pivot and starting using C#. I don’t know enough about the current Lua community demographics to give an effective suggestion, but my gut says just use C# compiling down to Lua for v3 until v4 can be fully baked with it… or not. There are native speed ramifications that C# can offer, but the engineering effort is quite profound. :: flips a coin ::

Bottom line, Lua ain’t it, Java or C# is. ECMA 6 is out merely because it has a web bent. Corona, currently, doesn’t need the web developer demographic. Yes, sharing libraries and having Agencies whipping out cross compiled applications using Corona SDK vs. Appcelerator is great for initial growth and platform relevancy & validation since Agencies are first movers, but that’s not the demographic we want. We want B2B consultancies and software shops. They ain’t going to jive with this Lua nonsense when building larger initiatives.

Workflow

The workflow support, right now, is pretty harsh. My ghetto setup with Sublime and my colleagues support in testing various other implementations randomly found on Github is an indication of how much work there is to do.

Specifically, 3 things need to happen:

  1. We need an official IDE.
  2. We need v3 and v4 Components to default to the viewport style scaling for applications.
  3. We need on-device debugging.

IDE

I don’t care what is chosen; Eclipse, IntelliJ, or even Sublime. Bottom line, we need intellisense & code hinting/completion for both productivity and teaching the API, the ability to set breakpoints and step through code (even just forward as opposed to Lua Glider’s backwards ability), and package/class/refactoring support. This includes the IDE’s ability to know what a class is so when we refactor it, it can change it, not just some “move” option. IntelliJ’s a good example for this, but ultimately anything that even copies 10% of Visual Studio is a win.

This includes v3 and/or v4 API’s. If a cross compilation is chosen, it needs to implement source maps to ensure the compiled code can re-map back to the the development code.

I personally prefer IntelliJ, but it’s slow as all get out on Mac. Eclipse is a stamp of acceptance from large companies, so I’d reluctantly recommend it since you’d at least be immediately perceived as wearing a collared shirt and tie to get into the exclusive enterprise club from a development standpoint. This also spits in the face of the “immediacy” philosophy that Corona SDK currently has, so… I’ll just sit by and let Corona make the hard choices while I critique from afar.

Viewport

A quick note on Viewports. The existing Viewport options in Corona are confusing, and I’d argue all applications, not games, only need 1 option that can be a standard config.lua provided to all (yes, ALL) Corona SDK applications. They should draw to the size they have and allow Corona SDK to scale up based on the existing DPI.

Right now this topic is kind of “flexible” because each game is created differently, for different devices. Apps are not. There is a reason why responsive design took off in the web world: because it works both from a technical perspective, and from a business one. The implementation details are tons easier on Corona SDK, however, and this ability should be capitalized on by further making it more simple: unknown to the developer so they only care about the DPI they are targeting, period.

The existing Corona graphic support of high rez is great, it just needs supplementation with v3 abstracting this away, and the developers responsible for their own form/composition component layouts. To be clear, I’m not suggestion a point based system like iOS does, simply defaulting config.lua to a letterbox scale, a specific device size, and the v3 components will handle detecting the API unless one is set in the config.lua so it can scale accordingly.

The IDE should code gen this for you; developers should NOT be messing with this beyond project setup. Obviously it’d be nice to have more support in the simulator to know what DPI you’re really looking at. The amount of current Stage properties regarding with, height, and scaling are indicative of the current problem we have. Moai style exposure of lower level size constructs are NOT a good thing and this is not congruent with Corona SDK’s ease of use & development speed philosophy.

On Device Debugging

Not much to say here. The use case is I set a break point in the IDE, hit run, it launches on my connected device, and the IDE pauses the runtime on the current break point I set in the code. I can then step through the code and see the variable values.

Conclusions

As you can see, the above is a ton of work, and a multi-year initiative even assuming the capital investment is there. The justification is that the mobile industry has billions in growth, and with the death of Adobe AIR (death by no one caring because of Adobe’s “doubling down” on HTML5 vs. Flash in case I get ravaged in the comments), Corona is ripe to leverage it’s cross platform development and deployment runtime + growing plugin market place to really make some serious growth here.

One thing working with Corona the past 2 years has taught me is that there is always more to learn about our industry, not just by using another technical stack, but also another market segment at the same time, in this case gaming. In doing so, I’ve met a lot of new people who’ve taught me a lot I didn’t know about how products in this vertical work. Given that companies like EA have adopted Corona Enterprise as a vehicle for some of their offerings, it’d be strange to see Corona pivot and go enterprise app dev, opposite of the path Adobe took with the Flash platform. That said, the ground work is there, you just need 3 years, more investment, hard work… and some luck.

Speaking of which, I’ve spent over 2 years having fun with Corona in a hobby capacity, and haven’t made any money on a platform I’ve invested so much time. I don’t mind since it’s been purely a hobby, fun, and a way to get out of my comfort zone (ie game dev vs. application dev). That said, this is not rose colored glasses talk. There is a great opportunity here, and I believe in the platform solving these mobile development problems. Companies are using the HTML stack on top of PhoneGap because they have to, not because they want to. That, and the innovation is going way too slowly for what we need. The simplicity of Corona combined with some API improvements, a solid component set, and a reasonable IDE are all we need, the above is just the ideal. This won’t supplant the existing competition; we’re already in a red ocean here. It WILL however, really create a lot of great opportunities for those wishing to build mobile applications faster and easier.

If you agree with the above, bring the ruckus on the Corona forums. Let ’em know this is valuable to what your company is building, wants to build… or is the complete opposite of what you believe Corona should focus on.

6 Replies to “Taking Corona SDK to the Next Level”

  1. So much here it’s almost TLDR :) but I’ll just note that WRT components/widgets, I am not sure the Corona folks look at the framework for building utility apps. Which is a shame b/c that’s really where the consulting money is, not so much for games. +1 and 100% agree we need a Sencha-style MVC framework. Been saying that for a long time, and I feel that junior devs can get into some really bad habits as coders if they cram everything into main.lua. Regarding language choice, I think the investment in lua is very profound, but allowing authoring in a diverse set of languages is an interesting idea. In my survey of devs at the Boston Festival of Indie Games last year, almost everyone was writing in C-something.
    Really interesting and good ideas :)

  2. Good ideas and well explained. But since this is sooo much work, I think it will never get there.
    I’m a b2b app developer, using Windows and I continuously struggle with the simulator not being able to display the native widgets. This is really frustrating as testing on a device takes 10x longer and there’s no debugging :(

    I’m looking at other high level SDK’s but can’t find one that appeals to me. I dislike web tech (Javascript, HTML5, CSS).

    Any suggestions?

  3. Jesse – we saw your post a while back and discussed it internally. I just realized we never posted here, so doing it now. THANK YOU very much for taking the time to write this. We really appreciate it. This is all fantastic feedback and we are paying attention. Of course, as you clearly realize, this is a ton of work :) But we plan on getting there.

    Of course, feel free to email us any time. My email (which I think you have) is david AT coronalabs

Comments are closed.