Wednesday, December 13, 2017

Lose the head – Tag!

OutSystems 10 brought the wonderful world of low code to mobile application development. Now, it's about your ideas! Want an app to take pictures? Just "drive" to OutSystems Forge and look for the Camera Plugin and use it in your app:

OutSystems Camera Plugin

There are literally hundreds of plugins out there to interact with basically everything on your device, from accelerometer to camera, GPS, etc. OutSystems has a list of supported plugins, which means that not only you get official support if anything is wrong but the plugin is also properly maintained and evolved. However, the great power of this plugin mechanism is that the community is able to develop whatever plugin. Anything! Hey, I've created a plugin to keep the Android screen alive all the time. There's documentation on how to create a plugin, but I want to highlight a critical aspect of plugins.

OutSystems mobile apps are cordova based. This means that, potentially, any cordova plugin can be used in your apps ("potentially" because some plugins might not work - e.g.: because they are built for Android 2.3 (low target SDK), they don't have iOS implementation, etc). Lets head back to the Camera Plugin. To use it, you have a client action, "TakePicture". But what does that mean? Taking a picture is something that implies specific native iOS and Android commands. So, how is that client action doing the magic? Well, an OutSystems mobile plugin is actually composed by two distinct parts:

OutSystems Cordova

How does everything work together? Where's the glue? A bit more low level:

OutSystems Cordova

Looking at the image, you can see where the logic separation is between OutSystems and the native code. A cordova plugin basically exposes a Javascript API that OutSystems plugins ultimately call. There's still a missing piece: how does the platform know what cordova plugin you want?

OutSystems Cordova

It's in the OutSystems plugin extensibility configurations.

OutSystems Cordova

The camera plugin uses an URL to refer to the native part. When you request a native build of your mobile app the OutSystems Mobile Apps Build Service (MABS) will then use that URL to fetch the code for the native part of the code and include in the build of your app.

OutSystems Cordova

Now, here's the detail: did you notice the URL of the plugin?

https://github.com/OutSystems/cordova-plugin-camera#2.3.1.OS

It contains a what is called a tag (or release). This instructs the MABS to get that specific version of the plugin and not the latest and greatest. This is a best practice: do not use the head of the master branch. Weird? Let's see why I'm stating this. Assume you have no tag; Without the tag, you are using the latest commit someone did to an open source project, the camera plugin. How risky does that sound? A lot. There are tests and so on, but still, it's risky! Considering this, imagine the following scenario: you started a project for a mobile app in February and included a plugin with no tag. 2 months later you go to Quality Assurance processes and, after 1 month of proper validation, you're ready for the go live! Well, someone commits in that repository and... bum! Everything is broken or it's not working as it did before. Or now it's compiled with 64 bits library and you are also using another plugin that conflicts with that. Or...
You get the point. You didn't do anything and, all of the sudden, your project is no longer ready to go live. It's a free run and you have no control. You are totally dependent on "strangers". And this gets darker: someone might not commit on the main repository of the plugin, but the plugin is referencing the head of some depending libraries and someone commits in that dependency repository. Now it's even harder to understand why things suddenly stopped working because it's not obvious, there are no commits on the main plugin branch!

So, rules of thumb:
   1. If the plugin is critical for your business => create a fork to your own repository and merge as needed (OutSystems does it for the supported plugins)
   2. Make sure the plugin's dependencies use tags.
   3. Always, always, always use tag. Control your release.

Happy plugins!

Friday, September 29, 2017

OutSystems mobile app at scale

The goal of this post is to actually provide some tips when using OutSystems 10 to develop Mobile apps. It's so easy to develop an app using the platform that sometimes we tend to forget a few things that might be important at scale. So, if you're planning to build the next Facebook using OutSystems 10, keep reading. Tip 6 is the more important.

1) Don't run away from the stores
It's a fact: you're not in control anymore. With web apps, whenever you wanted a customer to get a new version, you just had to "One-click publish" and that was it. "Hit F5 and you're done". The happy path simplified:

One-click publish

Ok, here we're ignoring all the operations behind it (from development to production). With this "web", you could still have issues that you must keep an eye on: add a proxy, bad network, cache servers, load balancers and a huge frontend farm and the scenario gets a bit trickier:

One-click publish

Nevertheless, you have almost all the control (Days of thunder - Control is an illusion). Why should the mobile world be any different? OutSystems 10 brings you Mobile Apps with an amazing capability: no need to go through the stores to push a new version to your customers! There are lots of applications that do this already, even facebook (facebook lite app):

Facebook Lite

This is a huge advantage (pushing updates to the customer on-the-fly) because it no longer implies a round trip to the stores. So, looking at a typical update scenario:

OutSystems update

Looks like "the web" scenario where your "One-click publish" goes to the customer in seconds. So far so good, the happy path is always a delight. However, this feature doesn't mean one submit to the stores for life. The mechanism that checks for updates will get the "delta" from what's new in the server and what the customer has:

OutSystems Lifecycle app
(click to enlarge)

As you can see, if the customer is constantly picking up the updates we're again in a happy path. However, imagine a customer that installs the app from the store 2 months after your release in the store. When he opens the app, the in-app update mechanism will check for updates and see that there are 1120 new changes (V6 is in production). If the files have, in average, 10KB each, that will imply approximately 11.2MB for the update. This will bring overhead and, in bad networks or network transitions (e.g.: entering an elevator, subway, etc), might not be smooth (2G).

So, tip number 1: don't run away from the stores. Create checkpoints whenever you start to witness a big difference from the original submit. It's a balance.


2) Understand the upgrade model
The updates "on the fly" are amazing, no doubt. However, some features require a new shell (e.g.: using a new plugin that interacts with native features - camera, bluetooth, NFC, etc). Now you'll have to deploy your app to production and go to the store. Let's go with an example: suppose you have an app and now you add a functionality to scan QR Codes by clicking a button. You go to the OutSystems Forge and grab the supported Barcode plugin. This requires a new shell as it now interacts with a native capability and code to interact with the camera. How to "glue" everything? Publish to the store first? Deploy to production first?

OutSystems update

Let's look at this scenario. The first thing you MUST do is to protect your code to not "blow" if the plugin is not there. Hide the button, provide a graceful message to the user when he clicks, whatever. Just make sure you don't try to scan if the user doesn't have the plugin. This is a must do no matter what's your deployment strategy. Now, for the complete experience to be in the hands of your users they will need to have both a new shell with the plugin and the logic in the app.

#First approach - long time prepare
If you know you're going to need this plugin, release today a new shell in the stores. Wait a few weeks until your customers update to the new app from the store (or force that update in the app). After that, deploy to production the new feature.

OutSystems update

#Second approach - Deploy code first
You might not be aware in advance that you'll need a given plugin. So, you can't prepare it so easily. Go to production with the code protected and deploy to the stores right afterwards. You must properly protect the feature to scan the QRCodes.

OutSystems update

Keep in mind that unless you programmatically force the user to update from the store, you don't control how much time the user will have an old shell:

OutSystems Lifecycle app
(click to enlarge)

Tip 2: Keep in mind that although you have the applicational updates "pushed to the client", native functionality will go through the stores and you must have a combined strategy.


3) Caution with infrastructure
If you're not in the cloud and have the responsibility to have all the infrastructure in place, then, besides all the work you'll have, you will also be the one dealing with cache servers, load balancers and several frontends. So, this means that in a deployment to production, some customers might get a new version while others don't. Some might be affected by cache poisoning (e.g.: Cache is returning bad JavaScript files while returning new HTML files...), others might not.

OutSystems update

Tip number 3: properly setup the production infrastructure and be aware how you deploy to production.


4) You will have a customer with a rooted Xiaomi 3422-y-k-x-a-89002893-whatever-the-model-it-is
This isn't something particular to OutSystems. It's on all Mobile. Due to the market fragmentation, particularly in Android, you will have a customer with a Xiaomi model that something will not work. YOu don't need to avoid that, but protect your app to avoid possible unhappy users. Example? Do you want to accept rooted Android devices that you don't have the slightest idea of what's hammered or not? How will you deal with a complaint from a customer using a device you don't have access to?

Tip 4: Prepare yourself to customer's free of will to buy whatever mobile device they want and you not having access to it.


5) Phased rollout is king
Because the control you have is little, a phased rollout is almost mandatory. YOu have the ability to push improvements to customers, take advantage of that and do a DevOps approach, releasing things to internal users first, then some customers, then... It's the same logic that TestFLight and Play Beta use, but faster and better! Maybe you have the new button to scan QRCodes. Well, make it visible to a given set of internal users or friends. Then open to the world.

Tip 5: Take advantage of the fast updates to gather feedback faster from a subset of your customer base.


6) Just because it's easy...
... doesn't mean you don't have to read some documentation. Most developers out there are used to a web world where the concerns are totally different than mobile. Performance, battery consumption, network conditions, device fragmentation and all those mobile world intrinsics must be a primary concern from the first day of the project.

The technology makes it easy to bring your ideas to life. But you still have to care for your ideas and your project.

Tip 6:

Saturday, July 22, 2017

Going beyond with your OutSystems Mobile App

Creating a native mobile app with OutSystems is so easy that it's scary! Just a few clicks and, in a few minutes, you'll have an iOS and Android application. Out of the box, the resulting app will look like this:


Simple. It's your show now, your "drawing board". Create!
This is the common pattern. However, before you go public, you should do the final tweaks. It's that extra mile, that "wow factor", that "5 star rating" that you must go after. Did you notice the "glitch" on app startup? Take another look at the video. What's happening is that the native splash screen wasn't customized and you're seeing the black screen (Operating System starting the app) and then a white "glitch", which is actually the webview loading content (OutSystems apps are Cordova based).

What happens OutSystems app start
What happens by default

To create that super user experience, you just have to do some small steps as described in the documentation: Use Custom Splash Screens. In the article, the splash screen will disappear after 3 seconds (enough time to load the webview) but, if you want, you can have fine control over the hiding of the screen. The result will be an app that gracefully starts:


The graph is now different:

What happens OutSystems app start
Fast feedback to the user

If you're having troubles following the documentation, I've created a small video on how to do it. Here it is:


Here's a MyResources.ZIP and here's an Extensibility Configuration JSON to get you going. This is valid at the time of the writing of this post, it might change in the future as Apple and Google change resolutions. You should keep an eye on the documentation.

Wednesday, March 29, 2017

The next train to production

Most of my professional life was spent working with banking, insurance, telco and media. Clients with mature processes in place that yield predictable results. In these industries, "safety is king". They are "control freaks"! And Cloud solutions are only "a dream" on most cases. On premises is still how they live. So, with this mindset you can expect (lots) of bureaucracy in place when staging software. The focus is not on "rapid continuous delivery" but rather more complex release processes spread through wider release cycles. They privilege stability over "the latest and greatest" that comes out of whatever software provider. This isn't a problem "per se". It's methodologies they've been maturing for decades to fit their business goals. Now, having said all this, you can expect the complexity illustrated below for a typical staging scenario in these types of clients:

Staging Environments
(click to enlarge)

Again, keep in mind this scenario is all using on premises.
So, how does your code get to production? Send a Zip file? Well, it's not that simple. Safety first right? Risk aversion! You might have noticed that I separated environments by team types: Development Teams versus Operational Teams. Project is rolling and it's time to got to production. Until QA, it's up to the development teams to promote software in a repeatable process that can be easily replicated. The jump to QA typically implies filling a rather complex form (normally using Change Management tools) with lots of info, namely, "why is this going to production", "impact analysis", "risk analysis", "who authorized", "who's the business group that requested the features", "who are the business users that will validate things... and on and on.

Staging Environments
(click to enlarge)

It also implies instructions to operational teams on how to deploy, rollback, etc. This is very important because, from QA onward, the deploy in the environments will be in charge of operational teams that might not have the slightest context about what is going to production and what changes it implies. After some time, if QA is "ok" and property validated... there's another request to pre-production, identifying issues that appeared in QA, etc etc. To production! Even more complex because if it's an upgrade to an existing system with an agreed operation time of 24/7, then no downtime. You have to clearly state how is that "no downtime" guaranteed and a special authorization might be required. Ok, this is a 24/7 scenario but there are apps that can have agreed times to upgrade production.

Does all this sound like fun? No. But, again, safety first. Where does all this fit this post? Well, in a recent project we had to create a new system, from scratch. No environments setup yet, no processes in place. Just a blank sheet of paper and a white board for us to do our best.

Staging Environments

We started with only a development environment. That spawned to QA and, afterwards, production. Then... you see where this is going right? Well, not quite. Dev, QA and production are "olympic minimums". But more than that? Would you buy all the complexity from these industries? Maybe not. Maybe you value the "rapid continuous delivery". Maybe you just want some parts, the ones that do fit your use case. Processes? YES! Excess bureaucracy? Maybe not. Maybe not. We’re currently evolving our system to fit our needs. We recently created the concept of "trains" because it made sense in our context.


Summing up: The complex processes that are typically found in banking, insurance, telco and media are good learning points, but you'll probably want to create your own. Their processes were matured throughout decades to fit their needs. I've learned to appreciate them. I do prefer other approaches, but I recognize the value of all this for these clients.

If, like me, you have the privilege to define the future of your organization and build something from scratch: It's really amazing! Learn from good examples. Then build your own good example.



Tuesday, February 21, 2017

The weight of decisions – moral machine

At some point, if you're developing some system, you will have to make decisions. But what if your decisions have real life impact? If you had to choose between killing yourself or another person? What's the rationale?

Here's an interesting test:

(Click on the image. Then just press Start Judging. In the end, you'll have a nice report)


Thursday, February 16, 2017

Top 5 funny things about JavaScript

The year was 1995, Google wasn't born yet. Mark Zuckerberg was 10 years old. Javascript was making its first steps. 22 years latter and JavaScript is everywhere. It's probably one of the most simple programming languages around and it's a good choice for someone that wants to start programming. However, there are some funny things about Javascript that anyone entering the language might find odd. Here's my top 5 funny things about the language. Just open a Google Chrome window and press F12. Have fun.

#5 – null is not an object?
What does a null look like in JavaScript? Well, let's check:

null is not an object

Object? Shouldn't null be the absence of meaningful value? Well, yes. Despite the above result, null is not considered an instance of an object:

null is not an object

Looking at the language specification, you can see that:
44.3.9 *undefined value*: primitive value used when a variable has not been assigned a value.
4.3.11 *null value*: primitive value that represents the intentional absence of any object value.

So, it's a case of misinterpretation.

null is not an object


#4 – NaN is a Number
What's "Not a Number"? Well... a number!

NaN is a Number

Funny as this might look, there's more. Not a Number has "identity issues" and is not equal to itself:

NaN is a Number

Well, the technical explanation for this is complex and it's related to the types of NaN (quiet NaN and signaling NaN). You can read more here, but the real way to check for a number is using the function isNaN():

NaN is a Number


#3 – Math.min() > Math.max()
Hum... So, the minimum value is higher than the max?

Math.min() Math.max()

Let's look at what they "represent":

Math.min() Math.max()

Well, seems to be wrong. These don't represent the max or min values for a number, but actually functions that given two numbers return the max or the min of the provided parameters.

Math.min() Math.max()

But why Infinity? And, apparently, in the inverse order? Well, looking at min(), "all numbers that are lower than positive infinity should be the smallest from a list, if there aren't smaller". So, the below makes sense:

Math.min() Math.max()

Number 5 is the minimum between 5 and positive Infinity.


#2 – true + true === 2
Let's do the math:

true + true === 2

So, someone entering the language might think that true === 1. Lets check:

true + true === 2

As odd as it might look, it actually makes sense. "EcmaScript standard specifies that unless either of the arguments is a string, the + operator is assumed to mean numeric addition and not string concatenation." So, it was the sum of the conversion to integer. As for the second part, true === 1 yields false because it's also comparing type and

true + true === 2



#1 – 0.1 + 0.2 !== 0.3
This is the coolest one and it's not a bug or anything. And it actually happens on several other programming languages, like C# (.NET) and I've written about it in the past

0.1 + 0.2 !== 0.3

"Computers can only natively store integers, so they need some way of representing decimal numbers. This representation comes with some degree of inaccuracy. That’s why, more often than not, 0.1 + 0.2 !== 0.3."
You can read more here (Floating Point Math) and see the behavior in other languages as well.

There is more to it, but these are definitely my favourite. If you want more, there's a cool video about JavaScript:

JavaScript Like It's 2013 (OutSystems)


Here's the full presentation at OutSystems Next Step 2013.


What's your favourite JavaScript funny fact?