TwitterFeed

The Long Journey (part 3)

Despite my past as a Java teacher, I am mostly involved in iOS development. I have dabbled here and there in Android, but it’s only been for short projects or maintenance. My first full fledged Android application now being behind me (mostly), I figured it might be helpful for other iOS devs out there with an understandable apprehension for Android development.

Basically it boils down to 3 fundamental observations:

  • Java is a lot stricter as a language than Objective-C, but allows for more “catching back”
  • Android projects should be thought like you would a web project, rather than monolithic as an iOS app
  • Yes, fragmentation of the device-scape sucks
Fragmentation is the main problem

It’s been said a bunch of times, the Android market is widely spread in terms or hardware and OS versions. My opinion on the matter is that device fragmentation is the obvious downside of the philosophy behind the agnostic OS development, and not a bad thing in and of itself. Having a SDK that allows you to write applications for things ranging from phones to TVs has a lot of upsides as well.

The thing that really irks me is the OS fragmentation. Android is evolving fast. It started pretty much horrible (I still shiver at the week I spent with Donut, version 1.6) but Jelly Bean feels like a mature system. However, according to the stats out there, half of the devices out there are still running 2.3, which lacks quite a lot of features… I’ll try to avoid ranting too much about back-porting or supporting older systems, even though I have to say most of my fits of rage originated in that area.

Designing with fragmentation in mind

As I said in part 2, my belief is that designing for a large scope of screen sizes is closely related to designing for the web: you can choose to go unisize, but you’d better have a very good reason to do so.

What I think I will recommend to designers I might work with on Android applications, is to create interfaces arrayed around an extensible area. Stick the buttons and stuff on the sides, or have a scrollable area without any preconceived size in one of the two directions. Think text editors, or itemized lists like news feeds. It’s a luxury to have only a couple of form factors, when you think about it: Desktop applications don’t have it, web applications don’t have it, iOS might not have it for long. But when in the past, most of the designers I had to work with were more print-oriented (working with a page size in mind), nowadays it tends to be easier to talk about extensibility and dynamic layouts. But if all you’ve done is working with iOS applications recently, it might be a little painful at first to go back to wondering about item placements when you resize the window. Extra work, but important work.

Coding with fragmentation in mind

According to Wikipedia, less than one third of the users are actually running 4.0 and above. The previous version is something like a quarter, and the vast majority of the rest runs 2.x.

The trouble is, many things that are considered “normal” for iOS developers started appearing in 3.0, or 4.0. Just the ActionBar (which can be like a tab bar or a button bar, or both) is 3.0 and above (SDK version 11). When you think about it, it’s mind boggling: half of the users out there have custom-coded tab bars… That’s why Google has been providing backwards-compatibility libs left and right to support the minimal functionalities of all these controls we take for granted.

But it also means that as a developer, you have to be constantly on the lookout for capabilities of your minimal target device.

There. I didn’t rant too much. Sighs with relief.

But wait, that’s not the only problem there is with fragmentation! The other problem is power and RAM. Graphical goodies are awesome for the user, but they also use an inordinate amount of memory and processing power. As a result, the OS constantly does things to the UI elements: they get destroyed, shelved, or something, and switching between two tabs rapidly might end up in recreating the views from the XML each and every time, which means that you as a developer have to keep constant track of the state of the items onscreen. Again, this might be counterintuitive to iOS developers who are pretty much guaranteed to have all the views in the hierarchy pre-loaded, even though some of its memory might have been dumped (after having informed the developer it needed space and given the app a chance to clean things up… Otherwise the app is killed, to keep things simple).

The funny part of this is this is completely obvious. We are, after all, running on devices that for all their power compared to my trusty (Graphite, clamshell) iBook of 2000, are still tight and limited. Last millenium, I ranted a lot towards developers who didn’t understand that all the computers out there are not as powerful as their shiny new G4 with Altivec enabled. With mobile computing, we’re back to having to worry about supporting 3GS and iPhone 5s, and for Android, the area to cover is just wider.

Debugging with fragmentation in mind

Last, but not least, all of these previous points mean that making sure your app works fine enough on all your target devices means a lot of testing. And I mean a lot.

TROLL BEGINS

The few big Android projects I have seen from the inside had to have at least a dozen devices on-site to test/debug on. The wide variety of hardware components, combined to the specificities of each and every manufacturer (who like to override the standard hooks in the system with their branded replacements) made that a requirement for actual grown-up development.

Maybe that’s why Android devices sell more than iOS devices, since each developer out there owns a bunch of phones and a bunch of tablets, where iOS devs have at the most two devices to test on: the oldest supported one and the one the dev is actually using.

TROLL ENDS

Sorry. That troll might be a way for my subconscious to punish me about reining in the rants earlier.

For the somewhat (in theory) simple project I did all the coding of, we had to conscript a lot of friends for testing purposes. And most of the time, it turned out it was indeed necessary, as the wide variety of screen sizes, component parts, connectivity options, os versions, and system configurations (both on the manufacturer side and the user side), while it made for a fascinating survey, provided us with a borad spectrum of potential problems. Of course it wasn’t made any easier by the fact that setting up a computer to get the log of the device requires some technical skills on the testers’ part.

But, again, finding out a way to work fine on most devices forces developers to be careful with CPU and RAM, and designers to be more focused and precise in their work, which is something I’m all for. Java gets a lot of crap for being slow and clunky but the reality is that developers always took for granted a number of things, including a competent garbage collector, and some cool syntactic sugar, which made most of the programs I reviewed really bloated and… non-careful. I think that if a good Android app exists out there, it means that there are some very talented developers behind it, and that they might even be more aware of the constraints embedded/mobile programming thrusts upon us than iOS/console programmers.

In conclusion, because there must be an end to a story

All in all, I enjoyed developing that app for Android. I happen to like the Java programming language in itself, even though it gets a bad press from the crappy VMs, and the crappy “multiplatform” ports out there.

I might be a more masochistic developer than most, but I like the fact it forces both me and the designer to have a better communication (because of all the unknowns to overcome), and to write more robust (and sometimes elegant) code.

Of course, in many respects, when you compare it to iOS development (which has its own set of drawbacks), it might not feel as a mature environment. With all its caveats, its backward-compatible libraries, its absence of centralized UI “way”, and its fragmented landscape, it forces you to be somewhat of an explorer, in addition to being a developer.

But with 3.0 (and it’s especially visible in 4.0), it’s starting to converge rapidly, and one can hope that, once Gingerbread is finally put out of its long-lasting agony, we will soon have a really complete way of writing apps that can work on a very wide range of devices (can’t wait to see what the Ouya will have in store, for example) with very little tweaks.

But, once again, I used to write stuff in assembly or proprietary languages/environments, for a lot of embedded devices, and I might have a bias on my enthusiasm.

  

The Long Journey (part 2)

Despite my past as a Java teacher, I am mostly involved in iOS development. I have dabbled here and there in Android, but it’s only been for short projects or maintenance. My first full fledged Android application now being behind me (mostly), I figured it might be helpful for other iOS devs out there with an understandable apprehension for Android development.

Basically it boils down to 3 fundamental observations:

  • Java is a lot stricter as a language than Objective-C, but allows for more “catching back”
  • Android projects should be thought like you would a web project, rather than monolithic as an iOS app
  • Yes, fragmentation of the device-scape sucks
Android projects as Web projects

This is not about technology and opposing app developers to web developers. Android, with its Intents and Activities, layouts and drawables, resources of many kinds, memory management schemes, etc, felt like web development should be, to me. Now, let me put it out there: as you can see from the surrounding pages, I am not a web developer. But the HTML/CSS/Javascript feels much closer to Android development than iOS techniques.

The basics of View Management

I’ll set aside the hardcore way of doing things (that also applies to iOS dev), with only code. I’m talking about the more standard XML layout + corresponding class here.

In the resources, there is a bunch of subfolders for supporting multiple screen sizes, ratios, input types, and languages. Think responsive design in CSS. Once the correct set of items has been selected, it is passed along to the Java class (think Javascript) which will then access each identified item to modify it.

In the Activity code, it translates to inflating resources, then assigning stuff to them, including contents, onClick (familiar, yet?) responders and the like. But If you don’t do anything, it’s just a static page.

public class MainActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main); // this will select the activity_main.xml in the most appropriate res folder

        TextView helloLbl = (TextView) findViewById(R.id.hello); // find me the view corresponding to that ID
        helloLbl.setText("Yay"); // replace the current contents with "Yay"
        // ...
    }

    // ...
}

Graphically, since devices have a somewhat big range of ratios and pixel sizes, having a design that “just works” is kind of difficult. In my opinion, which is the one from a non-designer developer, it’s a lot easier to decide early on that one of the dimensions is infinite like on a web page (otherwise, precisely tailored boxes change ratios on pretty much every device), or to have controls clustered on one end of the screen and a big scrollable “contents” area that will resize depending on the screen you’re on (kind of like a text editor). Any other arrangement is a bag of hurt…

Contents lifecycle

Maybe it’s just the project(s) I have been working on, but it feels as though the mechanics of the view resembles what I have done and seen in dynamic web apps built around HTML5 and Javascript, rather than a pure PHP one where the server outputs “static” HTML for the browser to handle:

  • The view is loaded from the XML. At that point, it’s “just” a structure on-screen.
  • The callback methods (onCreate, onResume, …) are called on the Java side
  • The Java code looks for graphical items with an id (or a class), and fills them, or moves/resizes them, or duplicates them…

Some will say that the iOS side of development works the same (with XIBs and IBOutlets etc), and maybe they are right, to a certain extent. It just feels that the listener approach gives a potentially much more varied way of doing things, and that they are called very often: for example, since a text label will resize according to its contents by default, it will trigger a resize/reorganizing of the layout, which will trigger other changes.

And since any object in the program can be a listener / actuator for these events, there’s a lot of competition and guesswork as to what will actually happen. The text label may respond a certain way (which can be overridden), its superview/layout engine another way (idem), all the way up the chain, which will trigger some changes down the branches again. During an ideal (and somewhat simple) load layout -> fill data boxes non repeating cycle, my onMeasure method (responsible for giving out the “final” size my control wishes to have depending on a bunch of parameters) was called up to 8 times in very close succession.

But that same listener mechanism, so pervasive in everything Java, also opens a lot of ways to catch anything that happens in your application, from any object:

  • you can detect layout changes from the buttons it contains
  • you can detect a tap on a control (usually non tappable) from its neighboring on a graphical point of view, thus extending the “tappable area”
  • you can react to content changes and limit/alter them on the fly

But so do the other views in the frame, not written by you!

View lifecycle

For memory-obsessed geeks such as myself, the view retain/release cycle was some work to get used to: They are kind of like the tabs in your mobile browser. Sometimes, you browse a website, open another tab, do some stuff, and when you get back to the first tab, it’s completely blank, and reloaded. Or not. It depends on the browser’s memory handling techniques and the available amount of RAM, processing power, and the page’s javascript running scripts.

Since the views might be re-created from scratch each and every time, the strategy to hold on to some data becomes critical. Do you keep them as instance variables of the controller, potentially hogging up the RAM, but being readily accessible instantly? Do you serialize them in the Bundle that the system uses for that kind of things (which I guess is written to disk when the RAM is full) every time the view goes away, and therefore test on all the restoring methods (onCreate, onViewStateRestored, …) that some data is present, deserialize it and put them where they belong? Do you reload it from whatever web service they are coming from? Do you serialize them yourself on disk?

All of these mechanisms require a lot of testing on various low memory devices, because there are out-of-view things happening that will destroy your data from memory if you’re not careful. And although you won’t find yourself having pointers that look ok, but have been freed, some data might be invalid at the time you’re trying to use them.

To Be Continued!

Next time, we’ll discuss the extremely varied range of android devices your app might be running on!

  

The Long Journey (part 1)

Despite my past as a Java teacher, I am mostly involved in iOS development. I have dabbled here and there in Android, but it’s only been for short projects or maintenance. My first full fledged Android application now being behind me (mostly), I figured it might be helpful for other iOS devs out there with an understandable apprehension for Android development.

Basically it boils down to 3 fundamental observations:

  • Java is a lot stricter as a language than Objective-C, but allows for more “catching back”
  • Android projects should be thought like you would a web project, rather than monolithic as an iOS app
  • Yes, fragmentation of the device-scape sucks
Java vs Objective-C

Forget everything you think you know about Java by other means than actually coding something useful in it. It pains you when somebody says Objective-C is not a real language? That C is just a toy for S&M fetishists? Java has been around for a long time, and therefore is mature. What might make it slow (disproved by stats a bunch of times) or a memory hog (it has an efficient garbage collector) is due to bad programming. I had to code a full Exposé-like interface in Java, and I was going 60fps on my 2008 black mackbook.

But for an ObjC developer, it does have its quirks (apart from basic syntax differences).

Scopes are respected

That’s right. Even knowing the pointer address of an object and its table of instance variables won’t help. If it’s private, it’s private. That means, that, for once, you’ll have to think of the class design as well before writing some code. Quick reminder:

  • private means visible to this class only
  • protected means visible to this class and its descendants
  • package (default) means visible to descendants and members of the same package (scope)
  • public means accessible to everybody
Types are respected

Same here. You can’t cast a Fragment to an Activity if it’s not an Activity. Failure to comply will lead to a massive crash.

What you can do is test if object is of type Activity by doing

if(object instanceof Activity)
Interface doesn’t mean the same thing

In ObjC, interface is a declaration. It basically exposes everything that should be known by the rest of the program about a class. In Java, once it’s typed, it’s known. You make a modification in a class, it’s seen by every other class in the program. Interfaces are kind of like formal protocols. If you define a class that implements an interface it has to implement all the functions of the interface.

public interface MyInterface {
    public void myMethod();
}
public class MyClass implements MyInterface {
    public void myMethod() {
        // mandatory, even if empty
    }
}
There’s some weird funky anonymous classes!

Yup. It’s common place to have something like:

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        // do something
    }
}

What it means is “I think I don’t need to create an actual class that implements the Runnable interface just to call a couple of methods”, or “I’m too lazy to actually create a separate class”, or “this anonymous class needs to access a private variable of the containing class”.

Let me substantiate the last part (and pointedly ignore the first two): according to one of the above paragraphs, a private variable isn’t accessible outside of that class. So a class, anonymous or not doesn’t have access either, right? Wrong.

A class can have classes (of any scope, public, protected or private) defined within. These internal classes, if you will, are part of the class scope. And therefore have access to the private variables.

public class MyClass {
    private int count;

    public MyClass(int c) {
        this.count = c;
    }

    public void countToZero() {
        Thread t = new Thread(new Runnable() {
            public void run() {
                while(count >= 0) {
                    System.out.println(count--);
                }
            }
        }); // anonymous class implementing Runnable

        t.start(); // start and forget
    }

    // Just for fun
    public class MySubClass {
        private int otherCount;

        public void backupCount(MyClass c) {
            otherCount = c.count;
        }
    }
}

is a perfectly valid class. And so is MyClass.MySubClass.

Beware of your imports

Unfortunately, because of the various cross-and-back-support libraries, some classes are not the same (from a system point of view) but have the same name. For example, if you compile using ICS (4.0+) and want to support older versions, chances are you’ll have to use the Support library, which backports some mechanisms such as Fragment.

It means that you have two classes named “Fragment”:

  • android.support.v4.app.Fragment
  • android.app.Fragment

From a logical point of view they are the same. But they don’t have the same type. Therefore, they are not related in terms of inheritance. Therefore they are not exchangeable.

The order of the imports matters: the last one has a higher priority than the first one. So if you have:

import android.support.v4.app.Fragment;
import android.app.Fragment;

Fragment will be the modern version. It helps to see imports as macros: basically, you tell the compiler that “Fragment” expands into “android.support.v4.app.Fragment”. If you have two macros with the same name, the last definition wins. The same rule applies here.

Exceptions are important

A Java program never crashes. It bumps exceptions to the top-level calling function, then exits with a bad status code if that exception isn’t caught.

On the other hand, the IDE gives you a lot of warnings and errors at code-writing (ie compile) time that should be heeded. Methods declare the kind of exceptions they might throw most of the time, and not catching them (or not passing them to the caller) isn’t allowed. There are very few exceptions to this rule, most of them being in the “You didn’t program defensively enough” or “this is a system quirk” variants.

Say a method reads

public void myMethod() throws IOException;

The calling method has to either be something like

public void myOtherMethod() throws IOException {
    myMethod();
}

or it has to catch the exception

public void myOtherMethod() {
    try {
        myMethod();
    } catch(IOException e) {
        // do something
    }
}

Of course, catching a more generic exception (Exception being a parent of IOException, for instance) will mean less catch-cases.

The exceptions that aren’t explicit are (mostly) stuff like NullPointerException (you tried to call a method on a null object, you bad programmer!) or IndexOutOfBoundsException (trying to access the 10th element in a 5-long array, eh?). The other category is more linked to system stuff: you can’t change a view’s attribute outside of the UI thread, or make network calls on the UI thread, that kind of thing.

To Be Continued!

Next time, we’ll see the project management side of things!

  

Demodynamics

It should be clear by now: I am a geek. Aside from all the normal quirks, I’m a computer geek, which means that I dream about systems and I subcounciously try to optimize things, make them more rational if not more efficient… I’m told it’s borderline rude, sometimes.

Anyway.

There is one thing geeks and non geeks who actually encounter large amounts of people all at once agree on: we suck at demodynamics.

Look at a school of fish or a flight of sparrows. Even though they have no brain to speak of compared to ours, you don’t see them bumping into each other even though their speed and group density is a receipe for disaster. Imagine a bunch of people you say “run around for a half hour, but you have to stay together as a group” to. When you’re done laughing, you’ll know what I mean.

Why am I rambling about demodynamics anyway?

Well, professionally, you can draw a lot of parallels between the two following situations:

  • a group of people is supposed to run together towards a common goal without knowing the route and finding some difficulties along the way
  • a group of people is supposed to deliver a product that has been outlined in somewhat vague (from an engineer’s point of view) fashion

And you see the same kind of dynamics: people shoving, people showing off, but also people helping each other when facing a wall etc…

Yesterday, I was in the subway (but you can have similar occurences when driving), and a couple of ladies rushed past me in a corridor, only to go half my speed ahead of me, effectively blocking me, because they were side by side.

Now, the worst part is I don’t think they even realized. They were side by side because they were chatting, and going slower for the same reason. Whoever is placed in that situation will undoubtedly sigh heavily, at the very least. But the same can be said for people who honk at you when you can’t pass the truck in front of you, etc…

As I said, people suck at demodynamics. Evaluating the right time to yield a priority you do have, in order to fluidifying traffic for everyone, including you, is a hard thing to do, since you basically can’t trust anyone around you to act with the same plan, let alone intent.

When you think about it, it’s all about two things: telegraphing your intent (and your plan), and being on the lookout for other people telegraphing their intent. That’s level zero. Then you have to know when to enforce and when to yield, and telegraphing that as well.

Most people think the problem lies in the second layer. We are a competitive race, and we naturally expect our solution to be followed. But my impression is that we completely lack the understanding of level zero. It’s not that our plan is the best one… It’s that it’s the only one.

Talking about this to my friends in the business and outside of it, we kind of agreed that people who like to do things when they have to relinquish control to have a better time are the ones looking around for cues and avoid bumping into other people (as understood in a general sense): people who dance a lot, musicians, construction workers, military or military inspired people,…

In any project I go with, it is painstakingly obvious that if someone I depend on fails, I’m screwed. If for nothing else, that makes a duty of mine to help this person. To some degree, the same can be said about people “above” me. I have to point at potential problems early and help them make a decision.

Unfortunately, as with the people in the subway or on the road, it doesn’t seem to be that obvious. Here in France, we go back and forth on a mandatory class taught to all kids that’s called “civic instruction”, or whatever the name that thing might have these days. Is there any way we could make that a demodynamics course, or a dance class?

TBC

  

[CoreData] Migrating To A New Model With An Extra Entity

As I mentioned in the previous post, I ran into an annoying problem with CoreData very recently:

Problem: We needed to have an evolution of the model, which in its simplest form meant adding an entity.

Naive solution: Well, duh. Lightweight migration will work just fine. If not, just make a mapping model, and you’ll be fine.

Well, no. Every automatic migration ended up into a “Error: table ZRandomNumber_*WhateverRandomEntityFromYourModel* already exists”

After a lot of digging around, annoying any and every contact who remotely knew anything about CoreData, I managed to extract the actual SQL commands it was trying to execute on the SQLite database.

Guess what? it was trying to recreate some of the tables based on relationships (rightly assuming that some of them had changed or had been added, since I added an Entity). But one of them was getting mangled, because it incorrectly assumed none of the relationships preexisted.

Naive solution v2: Well duh, export the database to an agnostic format, then reimport it in the new model.

Yep. That actually works. But I have 140 entities, and close to 300000 rows. After 4h of crunching, I decided to stop the test.

Naive (and I mean REALLY naive) solution that actually works: Find a way to add your new entity at the end of the alphabetical list. That way it creates the missing relationships after having made everything was kosher. I’m not even kidding, I added ZZ in front, and everything just worked. Try it before you loose your own hair.

  

CoreData, iCloud, And “Failure”

CoreData is a very sensitive topic. Here and elsewhere, it’s a recurrent theme. Just last week I had a hair-pulling problem with it that was solved in a ridiculous manner. I’ll document it later for future reference.

This week, triggered by an article on the verge, the spotlight came once again on the difficulties of that technology, namely that it just doesn’t work with iCloud, which by all other accounts works just fine.

It is kind of frustrating (yet completely accurate) to hear from pundits and users that iCloud just works for them for most things, especially Apple’s own products, and that CoreData-based apps work unreliably, if at all. The perception of people not actually trying to make it work is that it’s somehow the developer’s fault for not supporting it. Hence this article on the verge, which highlights the fact that it’s not the developer’s fault. This is a good intent, but unfortunately doesn’t solve anything, since it kind of waggles the finger at Apple and doesn’t explain anything.

But what is the actual problem?

CoreData is a framework for storing an application’s data in an efficient (hopefully) and compact way. It was introduced in 2005 for a very simple purpose: stopping the developers from storing stuff on the user’s disk in “messy” ways. By giving access to a framework that would help keeping everything tidied up in a single (for the “messy” part) database (for the “efficient” part), Apple essentially said that CoreData was a solution to pretty much every storage ailment that plagued the applications: custom file formats that could be ugly and slow, the headache of having “relationships” between parts of documents that would end up mangled or inefficient, etc.

CoreData is a simplification of storage techniques maintained by Apple and therefore reliable, is the underlying tenet. And for the most part, it is reliable and efficient.

iCloud, on the other hand, is addressing another part of the storage problem : syncing. It is a service/framework meant to make the storage on every device a user owns kind of the same storage space. Meaning, if I create a file on device A, it is created on B and C as well. If I modify it on C, the modification is echoed on A and B without any user interaction. Behind the scene, the service keeps track of the modifications in the storage it’s responsible for, pushes them through the network, and based on the last modification date and some other factors, every device decides which files on disk to replace with the one “in the cloud”. The syncing problem is a hard one, because of all the fringe cases (what if I modified a file on my laptop, then closed it before it sent something, then made another modification on my iPad? Which version is the right one? can we mix them safely?), but for small and “atomic” files, it works well enough.

iCloud is a simplification of syncing techniques maintained by Apple, and therefore reliable, to keep the tune playing. And for the most part, it does work as advertised.

But when you mix the two, it doesn’t work.

When you take a look at the goals of the two technologies, you can see why it’s a hard problem to solve: CoreData aims at making a monolithic “store-it-all” file for coherence and efficiency purposes, while iCloud aims at keeping a bunch of files synchronized across multiple disks, merging them if necessary. These two goals, while not completely opposed, are at odds: ideally, iCloud should sync the difference between two files.

But with a database file, it’s hard. It’s never a couple of bytes that are modified, it’s the whole coherence tracking metadata, plus all the objects referenced by the actual modification. Basically, if you want to be sure, you’d have to upload and replace the whole database. Because, once again, the goal of CoreData is to be monolithic and self-contained.

The iCloud philosophy would call for incremental changes tracking to be efficient: the original database, then the modification sets, ideally in separate files. The system would then be able to sync “upwards” from any given state to the current one, by playing the sets one by one until it reaches the latest version.

As you can see, a compromise cannot be reached easily. A lot of expert developers I highly respect have imagined a number of ways to make CoreData+iCloud work. Most of them are good ideas. But are they compatible with Apple’s vision of what the user experience should be? Syncing huge files that have been partially modified isn’t a new problem. And it’s one none of my various version control systems have satisfactorily addressed. Most of them just upload the whole thing.

Just my $.02.

  

Reviews : Average And Mean{;ness;ing}

So… Highlight has been out for a few months now.

First off, I am extremely surprised it’s getting as much attention as it does (by that, I mean more than 0. I can’t quite retire with the money it’s made me so far). So, my deep and sincere thanks to all of you who actually went and shelled out a whole dollar on that program! I honestly didn’t expect to get the few hundreds of downloads I got.

Back to the topic at hand: for years, I have heard, and read, how dreadful one can feel after getting a bad review. Given the ones I got, I can sincerely sympathize.

The very first thing I did when I pushed the app on the store, was to set up a page explaining how the software works. And I made really sure that the main feature (global toggle for on/off) was visible in the first two lines of the description of the app.

Out of the 5 (yes… 5) reviews listed, 3 of them are along the lines of “hey this program is ok, but an awesome feature would be to have an easy way to toggle it on/off”. Let me state again that this feature has been built in the software since 2006. And that’s in the first 2 lines of the description. And it’s stated clearly in the help page. Oh and there’s a video to demonstrate the actual principle. So… Hum… Well… Duh? And that is the basis for a bad review… Thank goodness I wasn’t planning on living off this app.

The other two are a bit harsh in terms of language, but I think the point underneath is fair: the users seem to think it’s too limited for their uses. It is indeed a simple app, that has 6 “pens” and one color setting. It does nothing extremely advanced, but it works perfectly for me when I’m showing off a demo to a somewhat large audience. And there’s some really clever things going on under the hood, but hey… That’s not really something the users are interested in.

The most interesting part, however, is that I have included a way to contact me at pretty much every level of the help. And the interaction with people who wanted features, or reported bugs has been overwhelmingly positive.

I have no background in, and very little knowledge of, the marketing sciences. But my scientist/engineer mind can’t explain how all these statements can be true simultaneously:

  • everyone I had an exchange with loves the app
  • I am an obscure developer, making an obscure app without any buzz or marketing
  • the only reviews are bad AND wrong for the majority
  • I have a steady sale average week-on-week

And honestly, this really doesn’t make me want to care about reviews. Maybe if the reviews were all positive, I’d sell more stuff. But most of all, it makes me think that the whole review thing is biased.

To write a review, you need to either have a good reason, or some time on your hand. When you’re pissed about something (albeit wrongly, since the feature you are clamoring for is actually already in there… since day one), that’s a good reason. When you feel like the seller needs a leg up or cheering up, that’s a good reason, but the sentiment on injustice has to be quite strong, I guess. So in order to get good reviews (and maybe max out the sales), the seller needs to put an extraordinary amount of effort to elicit that feeling in the buyer.

I choose to treat my customers right: if I find a bug, I’ll fix it. If a user finds a bug, I’ll fix it. If a user requests a feature, I’ll try to talk about it to see if it can be a fit, and explain my decision to the requester. But an anonymous review on the store, by somebody who hasn’t even taken the time of reading the 10 lines for the manual? I’ll pass, thank you.

Am I wrong to think like that?

  

The Joy Of Dependencies

Whether on our favorite UNIX flavor, or on our projects, we are pretty much all dreading the time when we have to update the dependencies. What will be broken? How long will it take? How many platforms/users will we have to leave hanging?

We obviously depend on a number of libraries and pieces of code written in another time, for another project, and/or by somebody else. Whether it’s something big (like the OS itself — just read the forums for cries of despair), or small (OK, so, apparently, that lib takes UTF-8 strings instead of UTF-16 ones, now…), no dependency update is hassle-free and painless. None. Never.

Once upon a time, a long long time ago, in a city not that far away, I had to write tools for a small printing business. My major dependencies were the print driver (which drove a huge triple-rotor, 12 ink barrels, monstrosity), Quark XPress, QuickTime and MacOS (Classic, but I can’t recall the exact version number).

Once it was up and running, after a lot of sweating and swearing, they didn’t dare upgrade anything. If a customer came with a newer version of their XPress document, they just told them to export it again in a more compatible format. And that was it.

Nowadays, with users being informed constantly about updates (and not trained for it), it’s up to us developers to make sure we have the backward compatibility (what if a user upgrades our app, but not the system?), and the forward one (try to keep up with the general thrust of evolution and prepare the code for “easy” updates), and of course fixing the existing bugs.

This obviously adds a lot of overhead to our work, which is very hard to convey. “It’s the fault of that OS maker”, or “yeah but they broke it in that version of the lib”, is something a fellow developer might accept as an excuse, but a paying customer?

And we can’t blame them! How about if someone told you your car could only go on this freeway or in this town, but nowhere else, until they have upgraded the road? Especially if you don’t actually see the difference…

So we’re stuck between dependencies which evolve according to their own constraints and objectives, and users who legitimately want the thing they paid for to work. Not mentioning the apparently dreadful one-star-review (for me, it’s mostly people who don’t read the instructions, then complain about things that are stated somewhere, but hey…), it’s a reputation do-or-die. And our code is literally filling up with workarounds for this or that version of the OS, the libs we depend on.

Why do I go on about this anyway? Well three things: Yoann (@ygini on twitter) and I both had to upgrade our ports on a BSD, which is long and/or painful, because each lib depends on at least 3 others, and I tried to fix a few bugs in an old project of mine I will definitely release someday. Both of them took wayyyyyyyyyyy longer than any “regular user” would accept. We are talking weeks or days of down or crippled-service time here.

I am still looking for a way to make sure people depending on me make the difference between a lame excuse (“they changed something so it doesn’t work anymore”) and a good excuse (“they changed something so it doesn’t work anymore”), and will take any good advice on the topic.

  

Rule Of Thumb

Principles, rules and laws are essentially the same thing. I won’t bother you with a paraphrasing of my recent reading list, which includes Plato, Kepler and Douglas Adams, but for a freelancer, it’s important to differentiate what is what, especially for the Other Guy.

A principle is a lighthouse on the horizon, and it’s OK to veer left and right, or even ignore it altogether. That’s one end of the spectrum. At the other end of the spectrum, you have the Law, which, to quote Morpheus, will break you if you try to break them (and get caught, obviously).

There are varying degrees of rules in between, from the rule of thumb to the house rule. Which apparently is akin to law. Or so I’m told.

Moving on…

Developing a program is kind of a ninja split between the two: some rules are unbreakable, because of maths, and contracts and stuff, and some people try to impose on us rules that can (and sometimes should) be gladly ignored. Just look at some interface designs blatantly ignoring the rule that someone somewhere edicted, and look just plain awesome. Right?

I took a roundabout way to make that point but programmers tend to consider rules with a clear downshift on the “have to” slider.

But, as computers are very attached to their governing rules, humans go a long way to actually enforce them. Case in point: you’re asked to make a mockup app that will illustrate some concept or something. It’s about as easy as making a working prototype, sometimes, so we bend the Prime Beancounter Directive: we go beyond what’s asked. But it’s not what was covered in the Contract. So we don’t get paid. Or at least it’s very hard.

So the appreciation of this particular rule was apparently wrong.

The problem is twofold: the question of the rigidness in the expression of the rule, and whether the Other Person tends to respect the spirit of the rule rather than the letter of it.

For the second part, it’s a lot easier to hide behind wording and you-have-to-s than to imagine what the intent of the rule is. That’s how we get “warning hot” on coffee cups (wait, what? I specifically ordered a lukewarm boiled cup of coffee, not that seemingly delicious cup of joe!), or “do not dry your pet in it” on microwaves (I won’t even bother). As weird as it sound, stupidity is foolproof. Adhering completely to blatantly stupid explicit rules is what makes the world tick smoothly it seems. For more on that, see the Miss Susan vs Jason, in Thief of Time.

You soon learned that ‘No one is to open the door of the Stationery Cupboard’ was a prohibition that a seven year-old simply would not understand. You had to think, and rephrase it in more immediate terms, like, ‘No one, Jason, no matter what, no, not even if they thought they heard someone shouting for help, no one – are you paying attention, Jason? – is to open the door of the Stationery Cupboard, or accidentally fall on the door handle so that it opens, or threaten to steal Richenda’s teddy bear unless she opens the door of the Stationery Cupboard, or be standing nearby when a mysterious wind comes out of nowhere and blows the door open all by itself, honestly, it really did, or in any way open, cause to open, ask anyone else to open, jump up and down on the loose floorboard to open or in any other way seek to obtain entry to the Stationery Cupboard, Jason!’

Loophole. The Dreaded Word by the Rulemakers. The Golden Sesame for the Rulebreakers.

But the power of a loophole relies solely on the fact that the rule is rigid to the point of absurdity. Of course, there should be an unbreakable rule that states that it’s not allowed to come to my home and take my hard-won computer for themselves. Of course there should be one for being able to tell a power hungry person that they overstep said power.

I guess the whole point is finding out where the rule protects a group of people from others and also from themselves. But when we’re talking about breaking a rule, in order to make something better for everyone, it’s an epitome of everything that’s wrong with our reasoning abilities.

And yet… I hear some of you think along the lines of “yea but if some rules should be put aside, how can that not be an argument for that there should be no rule, at least with some people?”. Strictly respecting all the rules makes it easier to have others respect all the rules as well, right?

Wrong.

Again, I think it’s a matter of harm. If by breaking a rule you harm no one (including yourself) in any way (except maybe their ego, but that has nothing to do with anything), then the rule is stupid. And should be ignored. Like, say, going beyond expectations. Actually, breaking a stupid rule should be grounds for an award, a compensation, something stating “wow, that rule was stupid. This awesome programmer deserves a raise. And he’s so cute too… <fawns>“.

Ahem. Anyways…

So then, I hear you think from here on my spaceship, how do you know you’re doing no harm? to anyone?

Dude, the daily personal and professional interactions we have are rarely a matter of life and death for entire nations. Business laws are supposed to protect me from getting screwed over by customers with no scruple. Not to prevent me from doing my job better than I’m supposed to. Fact is, most of the time, to enforce a “common sense” rule (getting paid for a job), I have to go through stupid rules first. And since the Other Guy is usually better equipped than I am to handle these first stupid hurdles, they win the race. So it spirals down: stupidity being the most efficient way, it becomes the norm. And we have to edict new rules to kind of balance the most stupid of our actions, or to close the loophole. Oh wait, another set of stupid rules to follow!

Stupidity is recursive. Thinking is hard.

The end doesn’t justify the means. Life shouldn’t be a permanent chess game either.

  

We Are What You Call Experts

OK, so France now has an experts board of digital something or other. Most companies I work with have hired, or will hire an expert to recommend stuff or audit stuff. And of course, even I get hired for expertizing stuff every now and again (go figure)…

As I stated before here and there, there’s something troubling about experts in what is perceived as my field. Experts in demolition or piloting, or botany, I get. These are highly specialized fields where it’s easy to spot an expert: they clearly know what they are talking about. You test them by asking them to do what they are experts of.

But in computer science, the field is so vast that it’s quite easy to pretend to be (or be mistaken as) an expert on one of the gazillions of subfields this domain has. Even family sometimes doesn’t get the fact that a coding or design expert isn’t the person best suited to repairing the printer…

Sometimes I feel like we are the doctors from the 1600s. We use jargon, we give off a vibe of tightly knitted hermetic community, and we wield an inordinate amount of power in regard to what we actually do, or know. Would you go to a vet to reattach your cut finger? Or go “hey come on, you have a medical degree, you can give me meds for my heart condition I think I have!” to a cousin who’s studying to be a chiropractor? (no offense to either of these fine specializations, it’s just to illustrate a point, I wouldn’t ask a heart surgeon to set a splinter either)

We live in a world of experts. Because of the high specialization of everything, you have to be certified, it’s harder and harder to switch fields, and the amateur sports are loosing spectators. But as soon as we are talking about computers, the expert status is somewhat murky. How many times do we freelancers have to “compete” with the second cousin of the daughter’s hairdresser, who’s “making websites”? Dude, I’m an app developer, I have a score of people I trust who can build an awesome website for you, why would I know anything about web technologies? I rely on… experts… for that… Can I dabble in it and commit an atrocity that would pass in poor light for something acceptable? Sure! Should I get paid for that? Hell no, there are people way better suited for that job. Could I? Probably.

Enough ranting, how can anyone rate somebody as an expert? In computer science, diplomas are not a sure way. Look at Mike, who’s clearly an expert, yet came from journalism. Portfolios are a good indicator, but only an expert can gauge the difficulty of the thing. Publications are yet another indicator (thank for reading this, by the way!), but with the Internet, the number of plagiarism cases is going through the roof.

“You are pretty bleak” I hear you think… But in all seriousness, I wouldn’t even know how to prove to you that I’m an expert. And by proving, I mean convincing you I know what I’m doing, without having to work for you for free to build something in an Internet-shielded room for a week. When all’s said and done, it’s just a matter of marketing myself. It helps that most people see computer science as some kind of magic, and are therefore highly susceptible to buzzwords and “hey I make loads of money in my work, that must mean I’m good, right?”. Wrong. Buzzwords are easy to acquire (read Plato’s Gorgias if you don’t believe me), and the money argument is a tautology and a self-fulfilling prophecy.

So to all of you awesome developers and designers and computer geeks out there who are really and immensely competent, yet don’t have the respect and credibility they deserve, kudos! And I’m sorry. I fear it will be a long time before there’s an objective way, accepted by most people, to finally get how good you all are. It took medicine a couple of millennia to go from “having a diploma” to “having a somewhat clearer way of discerning experts from fakers”. Hopefully it won’t be that long this time around, but I can make no promises. I’m not an expert in such matters…