Swift, c’est optionnel

Vous n’avez pas pu passer à côté de la nouvelle, Apple a sorti un nouveau langage de programmation, Swift, vendu comme étant « plus mieux mieux ». Une annonce sortie de nulle part et qui demande réflexion.

Beaucoup de développeurs ont déjà donné leur avis sur le sujet. J’attendais pour ma part de m’être livré à l’exercice de conversion d’une application existante. J’ai choisi ARD Inspector qui est une application simple (535 lignes) avec de la lecture de fichier, des collections, des tris, de la crypto… Bref, un candidat intéressant pour tester Swift de manière large sans trop perdre de temps…

TL; DR; Swift est un langage extrêmement strict fait pour des développeurs expérimentés cherchant la rigueur de code à tout prix et éventuellement la performance. Ce n’est pas un langage pour débutant. Il serait inconscient d’envisager débuter en développement Cocoa / Cocoa Touch directement en Swift.

Ce n’est pas une bêta, mais une alpha

Mon premier constat à l’écriture d’un code Swift est simple : soit je me défoule sur Twitter, soit le MacPro fait un vol.

Il est strictement impossible que ce langage et les outils qui vont avec aient été testés. La moindre écriture d’une boucle for fait planter violemment le compilateur.

swift_beta_jit_error

Et pour cause, à chaque caractère tapé lors de l’écriture de code, Xcode et son compilateur Just In Time (JIT) essayent de recompiler le projet. Sauf que vu que la ligne est en cours d’écriture, c’est impossible, le compilateur plante et les erreurs ne sont pas gérées.

Pour une alpha, c’est tout à fait normal comme comportement. Cela donne un simple indice du niveau de test effectué par Apple sur ce langage et les outils : proche de zéro.

D’ailleurs, la seule application annoncée comme étant écrite avec Swift est l’application WWDC de cette année. Une application simpliste qui avait des bugs assez énormes de téléchargement de données…

Lors de la présentation du Garbage Collector pour Cocoa sur 10.5, Apple avait au moins fait l’effort de s’en servir pour Xcode…

Le langage est simple à écrire… mais pas à comprendre

Une chose qu’apporte Swift par rapport à l’Objective-C, c’est la simplicité, au mauvais sens du terme.

Le langage est extrêmement épuré, compact, il permet de virer les points virgules, les parenthèses dans les boucles de contrôle. Bref, tout ce qu’un hipster-developer va aimer pour faire genre, mais qui va réduire la lisibilité du code, car, contrairement à l’Objective-C, la syntaxe est inconsistante et ne force pas à l’autodocumentation du code.

Là où l’usage est de faire des phrases en Objective-C et d’utiliser une syntaxe uniforme, Swift nous fait un mix des genres des plus discutable.

Prenons un exemple simple, la méthode outlineView:viewForTableColumn:item: du protocole NSOutlineViewDataSource.

La version Objective-C

ex1_objc

Et la version Swift

ex1_swift

Il serait aberrant de dire que la version Swift semble plus complexe. Moins de signes, plus de blanc, plus légers à l’œil… Bref, « c’est plus simple ».

Pourtant, si l’on y regarde de plus près, on peut être choqué. J’ai mis en couleur les noms des méthodes du framework Cocoa (qui est partagé par les deux langages) pour que l’on puisse mieux voir les choses.

Premièrement, regardons la première ligne, la déclaration d’un prototype.

En Objective-C, c’est assez cohérent. Le nom de la méthode est écrit avant les deux points qui précèdent chaque argument. C’est quelque chose de consistant à travers le temps et c’est stricto sensu ce qu’il faudra utiliser lors de son appel.

La même chose en Swift pose déjà quelque problème. Le nom de la méthode se trouve logiquement avant les parenthèses : outlineView. À l’intérieur des parenthèses se trouve la définition des arguments en trois points : le nom de la variable dans le code, son type, et son label.

Cette notion de label préfixant les variables à des fins de documentation d’une part, pour indiquer l’usage de la variable, mais a également un impact sur l’appel de méthode. Si la méthode outlineView est surchargée pour accepter différents types d’arguments, la sélection de la méthode ne se fera pas aux types des arguments, mais au préfixe que le développeur devra spécifier. Cela fait donc partie intégrante du sélecteur.

Mais, tous les labels ne sont pas égaux entre eux.

En effet, le premier label ne doit pas être spécifié par le développeur s’il n’impacte pas sur le choix de l’implémentation. Mais il doit l’être si c’est le cas, comme pour le constructeur de NSImage.

Les autres labels doivent être mis, mais pas forcément déclarés. En effet, le label par défaut des variables est le nom de la variable lui même. C’est implicite dans la déclaration, mais ce doit être explicite dans l’appel de méthode.

Pour se rendre compte, il suffit de regarder l’appel de méthode makeViewWithIdentifier:owner: de NSOutlineView. Un bout du sélecteur nécessaire à l’appel de méthode se trouve dans les parenthèses. Pourtant une rapide vérification nous permet de voir qu’il n’y a qu’une seule et unique implémentation pour la méthode makeViewWithIdentifier().

ex1_swift_autocompletion

Cela nous montre bien le manque de consistance du langage. Le premier label de variable ne doit pas être mis ici, sinon Xcode nous renvoie une erreur « Extranous argument label ‘identifier’ in call ». Par contre le second est impératif, sinon Xcode nous renvoie une erreur « Missing argument label ‘identifier’ in call ».

Par contre, si makeViewWithIdentifier avait deux implémentations avec des labels de premier argument différents, il aurait fallu le spécifier.

Tout cela n’est pas simple du tout.

Les API Cocoa… mais pas tout à fait

C’est là la différence entre Objective-C et Swift la plus sournoise. Certaines API ne se comportent pas de la même manière en Objective-C et en Swift.

Par exemple, la méthode allValues de NSDictionary renvoie un NSArray en Objective-C et un AnyObject[]! en Swift.

[] est un nouveau type introduit en Swift qui permet de faire un tableau d’objet d’un seul type spécifique. Si l’on veut pouvoir faire un tableau de tout type d’objet il faut le créer avec le type AnyObject qui permet de référencer tout type d’objet.

Ces tableaux Swift ne sont pas des tableaux NSArray, ils ne se comportement pas comme tel. Entre autres, pour trier ces tableaux, il faut appeler la fonction sort() qui est bel et bien une fonction autonome et non une méthode d’instance de la classe cible.

Problème de cette méthode sort(), elle doit être surchargée pour chaque type de collection. Des implémentations sont nativement présentes pour les types courants comme les Int, mais pour du custom, il va falloir se refaire l’implémentation soi-même là où il était simple en Objective-C de spécifier le nom de la méthode de comparaison à appeler sur les objet.

Les implémentations personnalisées de sort() travaillent avec des closures. Ce sont les équivalents des blocks de l’Objective-C. Son usage pourrait se rapporter à celui de sortedArrayUsingComparator:.

En Objective-C

ex2_objc

En Swift

ex2_swift

Cela fait la même chose, sauf que l’un et orienté objet et l’autre utilise une vulgaire fonction surchargée. Étonnant pour un langage qui se veut loin du C…

Et tu cast cast cast cette variable qui te plait…

Voilà la pire fonctionnalité du langage, la « sécurité » des types. On ne peut pas utiliser d’assignation dynamique d’un type à l’autre sans faire de cast explicite.

Mon code Objective-C ne contient aucun cast, j’en ai déjà 26 en Swift. Ça n’apporte pas grand-chose en fonctionnalité, c’est simplement une lourdeur qui impose de la rigueur de code.

Pas vraiment simple comme système, mais ça évite une partie des erreurs.

Intégration à l’existant

Pour information, je n’ai pas réussi à terminé la réécriture de ARD Inspector en Swift.

Les fonctions cryptographique de CommonCrypto ne semblent pas pouvoir être appelées depuis Swift (ou je n’ai pas trouvé comment) et le bridge Objective-C / Swift pour utiliser mon ancienne classe n’est pas stable aujourd’hui (c’est une alpha après tout), Xcode ne me génère pas les headers de bridge, malgré le réglage des noms de modules comme indiqué un peu partout sur Internet.

Doit-on se former maintenant ?

C’est là pour moi la question principale. Les centres de formations les plus « opportunistes » ont déjà annoncé leurs cursus de formation sur le sujet, les autres suivent le pas, forcément.

Les stagiaires et élèves commencent également à demander les formations en Swift et sur les forums les débutants complets qui veulent apprendre le code avec Swift pullulent.

Du point de vue du formateur que je suis, ne payez pas de formation Swift. Surtout pas maintenant avec des outils instables au possible.

Attendez un an ou deux que le langage et les outils soient matures et stables. Qu’on soit certain qu’Apple ne revienne pas sur certaines choses (comme ce fut le cas pour le Garbage Collector, un bout d’ARC et comme c’est déjà le cas sur Swift).

De plus si vous êtes débutant, ne partez surtout pas sur Swift comme langage d’apprentissage. Ce n’est absolument pas fait pour contrairement aux apparences. Ce langage a des complexités cachées assez grosses. J’en ai exposé certaines ici, mais il y en a des plus grosses comme le principe de variable optionnelle qui permet de gérer le cas des variables sans valeurs. Notion absente de tous les langages usuels et qui sera particulière à appréhender.

Vendre une formation Swift est une aubaine pour les centres de formation et les formateurs. Tout formateur Objective-C / Cocoa ayant de l’expérience saura enseigner Swift, la migration depuis l’Objective-C est somme toute assez simple même si elle est déroutante. Mais pour le stagiaire arrivant là sans connaitre le langage Swift et le framework Cocoa, ce ne sera rien d’autre qu’une dépense sans aucun retour sur investissement avant 2 ans.

Réfléchissez réellement avant d’acheter des formations Swift, souhaitez-vous payer pour être un hipster ou payer pour apprendre des choses utiles en production ?

Une réflexion au sujet de « Swift, c’est optionnel »

  1. Bonjour, si j’ai bien suivi votre article le meilleur moyen pour un débutant comme moi voulant se mettre au swift et à iOS en autodidacte serais d’apprendre dans un premier temps l’objectiv-c, Dans ce cas recommandez vous un tutoriel en particulier ( anglais/français ) ?

Laisser un commentaire