My feelings towards the Web platform are of disgust and delight at the same time.
The Web is the only way to reach almost everyone in the world, regardless of the operating system they use. If they have a smartphone and a data plan they can get my application. I only have to develop it once, swear for a couple of months on all those Android devices still shipping with a stupidly broken WebKit implementation and then I’m done.
On paper, the Web platform is a marvelous thing.
It comes with a price though: non-native UI, near zero integration with the operating system, abysmal performance. The fact that everything is built on 25 years of technology meant to render text documents is the proverbial icing on the cake.
Yet, armed with our rocks and hammers we keep trying to bang out full blown applications built on few good core ideas drowned in a sea of crummy ones.
The end result is that, while we are all carrying supercomputers in our pockets, most software doesn’t run any better than ten years ago. Instead, most web applications feel slow and bloated and you have to go to great lengths to do reverse that perception. Even big names realized that native applications are still the only way to deliver a great experience, especially on low end devices that don’t have all the resources to cope with the inherent inefficiency of current browsers.
It’s time to stop and rethink how we can improve the web platform for applications without making it worse for everything else.
I have this recurrent thought that maybe we could stop adding new features to HTML5 and instead create a new “rendering mode”, with an entirely different code path triggered by the presence of a special doctype. This could be implemented with a leaner rendering engine that could re-use some essential pieces from the legacy one, discarding all the rest to provide an efficient runtime. Here’s my wish list:
- I want XHTML back. HTML5 is full of corner cases and while XML is by no means easy to parse it is at least well understood and widely supported and a more predictable markup language.
- Be strict with errors, failing at the first one instead of chugging along leaving my application in an unusable, broken, state. If the underlying technologies are well documented and standardized I see no reason to accept malformed input.
- Get rid of the CSS box model. Get rid of flexbox. I want a real layout engine and there’s plenty of native frameworks to get inspiration from. AutoLayout from iOS? QML’s anchors system? Qt’s or Android’s box layouts with springs? I will take anything as long as I, the developer, can extend it with custom logic, just as I can do in any of the aformentioned toolkits.
I know that asking to break compatibility with the current Web is too much to ask, but the unwillingness to create a new “major revision” of the Web platform brought us here, playing catch-up with features native platforms had ten years ago.
At this year’s I/O, Google unveiled the next version of Android, codename “M”. This release focuses on incremental improvements, new APIs and refining the user interface.
Having experience with both Android and iOS SDKs, I can draw some parallels between them, to the benefit of my friends and colleagues working on Apple platforms.
One of the aspects that was covered is the new permission system, which is clearly inspired by iOS. Gone is the “permission wall” shown when users tap “Install” in the Play Store. The system will ask users to either grant or deny access to privileged functionality on the spot.
Each application gets, as soon as it is installed, network access and is allowed to read and write files in its own container. Additional permissions are requested and, eventually, granted as soon as the application needs them, with the operating system in charge to present a confirmation prompt to the user. This is quite similar to how iOS application have been working since the dawn of the AppStore.
What’s interesting is that the underlying mechanism is still the old, broad, and granular set of permissions we’ve been accustomed to since the first version of Android. What’s changed is just the user experience and a couple of new APIs.
Developers, in fact, still have to declare all permissions they need in
these permissions are now clustered into “logical groups” to make them easier to understand for end
users. For example the old
WRITE_CALENDAR permissions are presented to the
user as a single prompt to access the whole calendar. From an API perspective, you are still
requesting access to
WRITE_CALENDAR (or both) but, once the user grants or denies
a permission coming from a logical group, all permissions in that group are either granted or denied
at the same time.
This is, again, strikingly similar to iOS. When I request access to the address book, I’m given both read and write access simultaneously. I don’t have to request them separately.
Power users will be disappointed to know that the settings screen will only allow to toggle groups, not individual permissions. As a first iteration, though, this is good enough and still a vast improvement over the “wall of permissions” users have endured until now.
Developers must opt-in to the new scheme by telling the system that they target “M” by changing a
couple of lines in their
build.gradle file in a manner quite similar to how the “Deployment
Target” configuration parameter works in iOS.
Opting in to the new scheme comes with a price: applications now must degrade gracefully in case the permission is being denied and they don’t have to crash when the permission is toggled from the settings screen at a later date. Developers also should ponder whether it’s better to ask for all permissions when the app is first launched 1 or wait until the permission is effectively needed.
Old applications that target a pre-M version of Android will get the old “wall of permissions” at install time but users will still be able to toggle each permission group after the application has been installed. The settings screen will, in this case, show a warning telling users that legacy applications might misbehave when something is turned off, since old applications assume that all permissions were granted them by the virtue they are installed and running on a device. Once a permission group is disabled, the system supplies fake data to the application in the form of e.g. an empty address book, unavailable location fixes, and so on. The system won’t raise security exceptions.
Also, whenever a permission is toggled from the settings page, the application process is killed. This frees developers from having to think about permissions changing while an application is performing a long-running operation.
From a developer standpoint the API is really simple: you check if you have a permission with
Context.checkSelfPermission() and prompt the user with
Activity.requestPermissions() and then
handle the response in the
onRequestPermissionsResult() method in your activities.
One difference with iOS is that developers can’t provide an explanation to be injected in the system UI. Developers either have to “double-prompt” 2 or show a justification prompt after the user has denied a particular permission, then ask again. This last method seems to be the preferred one. Beware though, after the first prompt users are shown a checkbox to hush all future requests. It is unclear whether all dialogs or only those coming from a specific permission group will be hidden.
Unlike iOS it is also possible to cluster multiple permission requests together. The system UI will include a progress indicator in the lower left corner displaying how many more dialogs will be shown.
In some cases permission alerts can be skipped altogether by firing a system intent, delegating the action to a component for which the user might already have granted all permissions, and this is really what most developers should attempt to do before taking matter to themselves and use privileged APIs.
The new permission model goes definitely in the right direction and I can’t wait to see devices with Android M hitting the market, bringing users a refined user experience alongside all other new features and improvements Android has to offer such as Doze and Android Pay.
Hangouts requests access to the microphone, contacts and SMS at launch because these are needed to provide essential functions in the application. Google Keep instead requests access to the microphone when you first tap the button to record a voice memo. ↩
Double-prompting is the practice of showing an application-managed prompt before the one handled by the system. ↩
When many people (with “many” being >= 2) work on a project it is important to lay down rules that all developers ought to follow lest everyone starts doing whatever the heck passes their mind.
The first, and probably most important rule, is to force everyone to write in a single, uniform, style so that code looks like it was written by a single person. Software developers spend most of their time reading each other’s code after all.
This is how “The Style Guide” is born.
The pinnacle of software engineering civilization is an endless stream of words written on a wiki somewhere, by someone who is no longer working at the company. A text nobody reads nor follows because, let’s be honest for a moment here, when I’m solving a problem I don’t know nor care about your whitespace rules. I just want to bang some code on the keyboard to fix the problem at hand and then call it a day. Fixing style problems and cleaning up code usually comes at a later phase, if at all.
Don’t forget the political problem of “why do I have to follow Bob’s advice on this? He’s an asshole, he doesn’t get programming. I’ll get the last word on this one.”, which is a surefire way to waste everybody’s time and money fighting office politics. So, bonus points if conventions come from outside, so that any complaint can be immediately choked to death with a generic “they (the language designers) want that, not my fault”.
The point is, writing a style guide just for your project or company is a waste of time, unless you want to exercise your technical writing chops, in private.
Design automated tools and community-wide style guides instead, so that all code in the world written in a particular programming language looks like it was authored by the same person.
Go, however, is the role model to follow here since, for the most part, doesn’t even have a lengthy style guide. It has automated tools to fix mechanical style violations and others to warn about code smells 1. Integrations with most editors are readily available for built-in and 3rd party tools alike for maximum productivity. From day one. All of this is possible because Go includes libraries to parse source code right into the standard library, which makes it really easy to work on the AST and manipulate source code (take that, C++ 2).
If you are designing a new programming language, or working on an emerging one, take care to ship version 1.0 with a complete style guide and tools to parse, manipulate, validate, and fix source code. Every minute we don’t have to spend bike-shedding and following tedious issues that can be automated is a minute we can spend writing awesome code in your programming language. It’s in your best interest to make us, the users, happy and productive.
As for me, I will refrain from using new programming languages that don’t provide many of the facilities that I’ve come to expect from Go, Python, Java, and C/C++ (to a lesser extent) 3.
Some of them are shipped with the compiler and all others can be easily installed with
go get. ↩
C++ is famously the most difficult programming language to parse, which explains why, until clang appeared, many IDEs (with the exception of Visual Studio) couldn’t offer decent auto-complete support. ↩
I’m talking to you, Rust. ↩