Sugar

Sugar

Sugar is an open source library for Elements that aims to create a common set of classes that can be used on all supported target platforms – .NET, Cocoa and Java – in order to enable more code sharing between these platforms. It is available in for all three languages and on all three platforms.

Background

We look at Elements as a cross-platform compiler and tool for creating great apps on all platforms, and not as a tool for creating cross-platform apps.

Cross-platform apps (with some exceptions, such as back-end servers or command line utilities) suck – they settle for a "lowest common denominator" approach that makes them bad apps on all platforms. As such, we do not want developers to write cross-platform apps — that is, a single app that runs across different platforms.

What we do want to encourage (and enable) with Elements is for developers to create great apps on any platform they want. Oftentimes, this means creating separate versions of the same app for different platforms – for example two different versions of a mobile app, for iOS and Android. Or two different versions of your desktop apps, for Windows and Mac. Or an iOS and a Mac version of an app. Or…

The point is that to target each platform with a high-quality application, it is necessary to create separate projects, each designed from the ground up for the target platform.

That said, when you're writing three or more versions of the same application, you will want to share a lot of code. All of the UI and UX of the application should be platform-specific, as will be a lot of the interaction with core operating system services. But a lot of the business logic, the "meat" that makes up your app, can hopefully be shared – implemented once, and used (maybe with minimal $IF/#ifs), on all platforms.

That is where Sugar comes in.

What is Sugar?

Sugar is a library of base classes that compile for all target platforms (.NET, Cocoa and Java) and provide you with an identical API to work with these classes on all platforms. For example, when you write code that uses a Sugar.Dictionary class, this class will have the same methods and the same behavior on all platforms, so that the code you write against it, in turn, can be platform agnostic and compile for all platforms as well.

The Sugar library is not vast, but it does provide the key ingedients for being able tyo write a lot of platform-agnostic business logic code. It includes support for Lists and Dictionaries, Numerical conversions, XML and Json parsing and writing, working with dates and times, string encodings, locales, HTTP requests, access to the system environment, and more.

Using Sugar also provides a consistent string type across all platforms, including support for automatically treating string literals as Sugar.String.

How is Sugar implemented?

The way Sugar is implemented is quite nifty, and could only have been done in Elements: Sugar uses a unique language feature called Mapped Types for most of its implementation (in fact, Mapped Types have been introduced to the compiler especially for Sugar).

What this does is taking existing classes provided by the underlying framework and making them available as new classes, under a different name and with different members. So rather than reinventing the wheel and implementing its own versions of exiting functionality, Sugar (mostly) takes existing framework classes and just exposes them to you using a common API.

Example: Sugar.Dictionary

For example, all three target platforms already have a sophisticated dictionary collection class:

  • System.Collections.Generic.Dictionary on .NET,
  • NSMutableDictionary on Cocoa and
  • java.util.HashMap on Java.

These classes perform the same function, but they look nothing alike, so code written against any one of them would be platform-specific and not portable.

Sugar exposes each of these classes under the Sugar.Dictionary name, and with the same well-defined API on each platform. This allows you to write code against the Sugar version of the Dictionary class, and that code will be portable and compile for all three platforms.

Under the hood, the compiler does all the heavy lifting via its Mapped Types feature, so that your compiled code will actually end up using the underlying framework class – Sugar.Dictionary won't even exist in the finished executable.

There are several upsides to this approach. For one, it saves Sugar from having to re-implement (and re-test) existing, well-proven framework classes. For another, it allows for Sugar classes to be toll-free cast-able to their underlying framework classes, if needed. For example, you might want to pass a Sugar.Dictionary generated by your business code into a platform-specific part of your application – and that part can just use the class directly as, say, an NSDictionary, without any costly conversion. Because under the hood, at runtime, it is an NSDictionary.

Of course the Dictionary class is just one example of many. Sugar uses Mapped Types wherever possible, but also introduces some "regular" classes, where sensible, such as in areas where no proper reusable classes exist on one or more platforms. For example, Sugar.HTTP is a regular class that provides services for retrieving data from the network in various forms. Sugar.JsonDocument is also implemeted in pure Elements code.

In fact, if you look at the soure for Sugar.JsonDocument, you can see the power of Sugar itself in action, as the set of classes is implemented as pure cross-platform code on top of other Sugar types.

Scope

The Sugar library covers a variety of areas, and continues to grow over time – partly based on your feedback and contributions, and on your real world needs.

In fact, Sugar has been vastly expanded and improved with the latest Elements 9 release.

Let us know what you think, what you are missing or – even better – get involved by forking Sugar on GitHub and sending us pull requests.

Sugar is Optional!

Remember that Sugar is an optional feature. We pride ourselves for Elements targeting the native frameworks on each platform, and you will write a lot of great code with Elements that just uses those frameworks directly – same as you might right now be doing in C#, Java or Objective-C.

Sugar is not meant to abstract you away or protect you from the underlying frameworks, or to save you from having to learn the basic concepts of how these frameworks function and should be used from your applications. As such, its scope is a lot smaller than many other "cross-platform libraries" (or in fact as platform-specific abstraction libraries, such as the Delphi VCL).

Sugar is there to help you abstract those pieces of code that you want to share between platforms. It provides, by very definition, a compromise of an API that works on all three target platform, but may not always feel native on all three target platforms – platform conventions are too different to have a class with methods that "feel 100% right" on .NET, Java and Cocoa at the same time.

Contribute

Sugar is an open source project, and driven as much by our internal work as it is by contributions from the community of Oxygene, RemObjects C# and Silver users. Let us know what functionality you are missing, or maybe even consider contributing some classes yourself. Pull requests are always welcome.

As of Elements 8, you can contribute to and work on the Sugar project in VisualStudio or Fire, without needing an Oxygene license.

A pre-compiled snapshot of Sugar ships in-the-box with Elements, so you simply need to add a reference, to use it.

Sugar is an open source project and you can contribute on GitHub.