Jaran Flaath

Thoughts on life, work and the universe. Sometimes writing in English og noen ganger på norsk.

This is a repost of the original from my previous blog at https://world.hey.com/jaran.flaath

The official Android documentation gives little in terms of best practices around versionCode, apart from that it has to be an ever increasing integer.

We have been using the Git commit count as the versionCode, on the projects where I have been involved. This has been a success in most cases, however there are a couple of issues with this approach:

  • It requires external command line tools to generate the number
  • It does not work well with Github Actions (even if the workflow can be configured to resolve this, if you really want to use the Git commit count), and we have increasingly been moving projects to Github Actions
  • If you should deploy bundles from different branches with different commit counts you can run in to problems

The best would obviously be if we could have an automatically generated versionCode which require no external tools and no special configuration, that would be for ever increasing for every build.

The Proposal

The latest proposal on the table: The Time Based Semantic Version Code 2000 (TTBSV2K)

TTBSV2K attempts to turn the versionCode into something which can be decoded (relatively easy), is automatically generated and does not require any external tools.

TTBSV2K has the format:

YYDDDMMMM

where

    YY is the current year (last two digits): 22, 23, 24
    DDD is the day of the year, 0-padded: 001, 056, 366
    MMMM is the minute of the day, 0-padded: 0001, 0790, 1440

This gives you a more easily decodable versionCode: 220590790

The Code

For your Kotlin DSL app/build.gradle.kts file, add these imports to the top:

import java.time.LocalDateTime
import java.time.ZoneId

and put this somewhere else in the file:

fun generateVersionCode(): Long {
    val now = LocalDateTime.now(ZoneId.of("UTC"))
    val versionCode = "${now.year - 2000}" +
            now.dayOfYear.toString().padStart(3, '0') +
            (now.hour * 60 + now.minute).toString().padStart(4, '0')
    return versionCode.toLong()
}

If you're using the Groovy DSL, add the following snippet to your app/build.gradle file:

import java.time.LocalDateTime
import java.time.ZoneId

static Integer generateVersionCode() {
    def now = LocalDateTime.now(ZoneId.of("UTC"))
    def versionCode = "${now.year - 2000}" +
            now.dayOfYear.toString().padLeft(3, '0') +
            (now.hour * 60 + now.minute).toString().padLeft(4, '0')
    return versionCode.toInteger()
}

The generateVersionCode function can then be called where you set the app's versionCode:

android {
    defaultConfig {
        versionCode generateVersionCode()
        versionName "1.0"
        ...
    }
}

✉️ Feel free to email me your thoughts on The Time Based Semantic Version Code 2000.

Disclaimer: This versionCode scheme will no longer work starting January 1st 2100 00:00:00. If you believe your app will still be in production and on the Play Store on that date, you might want to add some form of warning for your future team mates – so they can prepare.

This is a repost of the original from my previous blog at https://world.hey.com/jaran.flaath

Think about how you consider purchases, new books to read and what apps to install: How often do you look at items with 3 stars and think “Hey, I'll try this one today!”?

We have a star inflation and it's causing us great disservice – both users and producers alike.

The 5-star system we are rating after today, is scaled something like this:

⭐️ = Terrible ⭐️⭐️ = Horrible ⭐️⭐️⭐️ = Very Bad ⭐️⭐️⭐️⭐️ = Bad ⭐️⭐️⭐️⭐️⭐️ = Good!

The result of this is that whenever we like something we give it 5 stars. If it's not pleasing us, we consider how little it pleases us and give it 1-4 stars.

How did we end up wanting to put so much effort into evaluating degrees of dissatisfaction, rather than focusing on the level of satisfaction? As we're seldom looking for things to give us various degrees of dissatisfaction, it would be much more helpful with a more granular scale of positive rating.

Also consider this: How do you judge whether to read the 4.2-star book or the 4.3-star book next?

I propose we start using this starring system instead:

⭐️ = Bad. ⭐️⭐️ = Ok ⭐️⭐️⭐️ = Good ⭐️⭐️⭐️⭐️ = Very good ⭐️⭐️⭐️⭐️⭐️ = Exceptional, life changing, out of this world!

5-star ratings should be held very high. Just providing good service, writing a good book, creating a good app, being your neighbour, or family member, is not a 5-star candidate. 5-stars should be innovative, something never seen before, something that actually transforms your life, or make you reconsider everything.

Spend more time evaluating the degree of positive impact, less time contemplating how much negativity you are able to feel for an item.

On the other side of the table, developers, authors, service providers are having a very difficult time finding their place, or improving on their rating, when the only thing considered valuable is 5 stars. In many cases they will also waste time chasing completely irrelevant rating targets.

“Our KPI for this quarter is to achieve a 4.7 star rating in the App Store!”

Why is 4.7 a good performance indicator? Why not 4.6? 4.3? Are your target customers those looking for 4.7-rating apps?

A lot of apps, books, services could get an average 3-star “good” rating and be perfectly happy.

Consider an imaginary local outdoor organisation. They have developed an app giving you access to local trails that are good for hiking. The app is not a design master piece, it's most likely not drastically changing your life. However, it may be a very good app for its purpose and target audience. A 3-star rating might be spot on for this app – just where it should be. If you go into the App Store and find such an app with a 3-star rating today, how likely is it that your first though is “This must be shit”?

Let's widen our rating scale and do everyone a much greater service when it comes to evaluating the actual quality, value and satisfaction. Let's stop the star inflation.

This is a repost of the original from my previous blog at https://world.hey.com/jaran.flaath

We love to obsess with technology. That new UI framework, that new paradigm for software design, functional versus object orientation, multiplatform versus native – there's no lack of technological details to immerse in and fall in love with.

Moving from backend to frontend over the last four years I've gotten a new guiding voice at the back of my mind: what will this do for the user experience?

How will choosing A over B impact the user and improve on their experience and help solve their problems? Because that's what most of us are in software development to do: We're facilitators of our users. Our job is to solve their problems, and if we can; delight a little on our way.

The focus should be on choosing the technology that is right for the team and right for the problem at hand, to enable the team to perform, deliver – and at the same time enjoy it. Whether you implement natively, with React Native, with Flutter or whichever technology you've got at hand does not matter in the long run. The key is having a functioning and thriving team capable of delivering on user experience, with a technology that they are well-versed in.

To deliver on user experience, maintainability is obviously key. Being able to maintain a healthy code base which is easy to reason about, will enable the team to deliver efficiently and with reduced number of bugs. Which technology or framework used to achieve this should come second.

Having a happy, well oiled team working in an environment they are comfortable and skilled in, is much more important to the success of your product and quality of your user experience, than whether you choose framework A or B.

For 2022 I challenge you to put user experience first and delight your users!

Enter your email to subscribe to updates.