Intermédiaire

Apple et le nommage des paramètres

1-obAm_vblOhOy2snpg19LAAQue ce soit il y a plusieurs années ou aujourd’hui, Apple, au travers du langage Swift et Objective-C, a toujours proposé une syntaxe particulière aux développeurs.
Avec Swift, les développeurs ont découvert une syntaxe plus lisible et moderne, même si celle-ci garde certains aspects de son grand frère, l’Objective-C.
C’est notamment le cas pour le nommage des paramètres, qui a toujours suscité la curiosité ou l’appréhension chez ceux qui se frottent à ces deux langages. Nous verrons comment cette pierre angulaire dans le développement d’applications Apple a évolué et quel sera son avenir prochain.

Parlons des avantages de cette convention

Si Objective-C est un langage réputé comme très verbeux et difficile à lire pour les développeurs, il n’a pas apporté que des points négatifs, loin de là. Je pense être plutôt exacte en affirmant qu’une grande partie des développeurs avec un peu d’expérience dans le langage Objective-C a apprécié, après un temps d’adaptation certes, la verbosité des noms de méthodes, ainsi que le nommage des paramètres.

On entend souvent dire de la part des grands détracteurs d’Objective-C (ce qui est un peu moins vrai avec Swift aujourd’hui) que le nommage des paramètres lors de l’appel d’une méthode est inutile et redondant : selon eux, une variable doit porter un nom assez explicite pour que le code soit compris facilement à la lecture. Loin d’être en désaccord avec cette logique, j’apprécie tout de même davantage lire un appel d’une méthode où je sais exactement à quoi va servir chaque paramètre, surtout dans une méthode qui en contient un certain nombre.

Par exemple, l’utilisation des paramètres nommés s’avère très intéressante dans le cas d’une méthode qui va permettre d’ajouter un élément dans un tableau à un index précis :

    [legoBricks insertObject: redBrick atIndex: 3];

Littérallement (sans s’occuper de la valeur des paramètres), on pourra lire cette méthode de cette manière : insertObject:atIndex:. On identifie directement les paramètres (un objet et un index) ainsi que leur rôle dans la méthode, sans avoir besoin de faire appel à l’aide pour voir la signature de la méthode à chaque fois.

Reste le sujet délicat de trouver un nom de paramètre pertinent, qui ait un sens à la fois à l’intérieur de la fonction qui l’utilisera, mais aussi lorsqu’elle sera appelée, mais nous verrons ça un peu plus tard.

En bref, retenons, pour la suite de l’article, que le nommage de paramètres tel que le propose Apple ne doit PAS être considéré comme un défaut en terme de développement, mais comme une manière différente (et moins ambigüe) de lire les méthodes.

Objective-C pose les bases

Comme rappelé dans le paragraphe précédent, Objective-C, en parallèle de ses défauts, prenait déjà le parti du nommage explicite de paramètres, comme le faisait le langage dont il s’inspire, le SmallTalk.
Concrètement, la définition d’une méthode ressemble à cela :

    @interface LegoAstronaut: NSObject
        /* déclaration de methode */
    	- (void)buildSpaceshipWithHeight:(int) height andWidth:(int) width;
    @end
    
    @implementation LegoAstronaut
    	- (void)buildSpaceshipWithHeight:(int) height andWidth:(int) width {
    		//code
    	}
    @end

Ici, outre la syntaxe peu habituelle pour un développeur C# ou Java par exemple, on remarque que le premier paramètre aura pour nom height, et… Attendez, le deuxième paramètre porte le nom andWidth ou width ? Eh bien tout dépend de quel côté nous nous plaçons. A l’intérieur de la méthode, ce sera sous le nom width que le paramètre sera utilisé.
En revanche, pour appeler la méthode buildSpaceshipWithHeight:andWidth:, il faudra donner à ce paramètre le nom andWidth. Cette dernière phrase étant certainement un peu floue, voici un exemple d’appel de la méthode buildSpaceship :

    LegoAstronaut *benny = [[LegoAstronaut alloc] init];
    [benny buildSpaceshipWithHeight: 12 andWidth: 42];

Encore une fois, mis à part les crochets et autres particularités liées au langage (qui ne sont pas le sujet de cet article) on remarque que lors de l’appel de la méthode buildSpaceshipWithHeight:andWidth:, le deuxième paramètre est appelé andWidth. Cela permet de lire et comprendre ce que fait la méthode de manière fluide, comme si on lisait une phrase.

Quant au premier paramètre, on ne peut pas vraiment dire qu’il porte un nom extérieur. En Objective-C, on va généralement compléter le verbe au début de la signature avec with…, from… ou by… par exemple. Dans notre cas, on retrouve withHeight: juste avant l’insertion du premier paramètre.

Finalement, pour revenir à la structure de la signature d’une méthode, chaque paramètre (sauf le premier) aura un nom local, utilisé dans le corps de la méthode, et un nom externe, qui sera concerné lors de l’appel.

Cette façon de faire n’est tout de même pas très pratique, et c’est en partie à cause de cela que l’Objective-C a la réputation d’avoir des noms de méthodes à rallonge. Mais c’est un fait auquel les développeurs ont dû s’accoutumer car, jusqu’à présent, Apple ne souhaitait pas changer cette convention.

Apple fait peau neuve avec Swift mais s’inspire d’Objective-C

En juin 2014, Apple annonçait la sortie du langage Swift, une alternative moderne et developer friendly, qui vise à remplacer à terme Objective-C, qui est aujourd’hui moins adapté aux besoins et considéré comme un peu vieux car trop proche du C.

Sans revenir en détails sur le sujet, Swift se rapproche beaucoup de langages largement utilisés aujourd’hui et en vogue, comme C#, Ruby ou Python. Cela dit, même s’il se revendique moderne, Swift garde certaines habitudes et conventions de son grand frère, et c’est justement le cas pour le nommage des paramètres.
Il faut cependant souligner que, bien qu’avec ce nouveau langage Apple conserve le nommage explicite des paramètres, on trouve tout de même un certain nombre de différences :
* les paramètres du constructeur d’une classe doivent tous être nommés au moment de l’instanciation
* l’utilisation du nom externe du paramètre devient optionnel

Le cas des constructeurs

Emmett_Lego_Movie1
Contrairement à l’appel d’une méthode, lors de l’instanciation d’un objet, que cela soit pour une classe créée par le développeur ou une classe déjà présente dans Swift, tous les noms de paramètres devront apparaître dans l’appel. Ces paramètres sont considérés comme des noms de paramètres externes, ce qui explique l’obligation de tous les nommer. Malgré cette appellation d’externe, il faut les différencier des noms externes pour les méthodes classiques. Mais plutôt que d’étendre ces explications peu concrètes, voici ci-dessous un exemple de classe avec son instantiation :

    class LegoBuilder {
	    let name: String
	    let isMasterBuilder: Bool
			
		  init(name: String, isMasterBuilder: Bool)	{
			  self.name = name
		 	  self.isMasterBuilder = isMasterBuilder
		  }
    }
    
    LegoBuilder(name: "Emmet", isMasterBuilder: true)

Sans surprise, on retrouve bien les deux paramètres name et isMasterBuilder définis explicitement dans le constructeur. Finalement, cela rajoute un peu de confusion par rapport à ce qu’on avait l’habitude de voir avec Objective-C, mais (teaser) fort heureusement cela va bientôt changer.
Tout de même, pour ne pas que le développeur s’emmêle les pinceaux, XCode fournit un coup de pouce en autocomplétant le code en fonction du cas dans lequel on est.

Les paramètres externes

Pour le cas des paramètres externes, avec Swift Apple a rendu la distinction entre le nom du paramètre interne et externe optionnel : le paramètre devra toujours être nommé, mais le développeur n’est plus obligé d’avoir un nom de paramètre externe ET interne, car le nom du paramètre pourra être utilisé pour l’appel et également à l’intérieur de la fonction. L’appellation des noms internes et externes est en quelque sorte fusionnée. On se retrouve ainsi avec une utilisation telle que présentée ci-dessous :

    func sayHelloTo(name: String, repeat: Int) {
      for _ in 1...repeat {
          print("Hello \(name)")
      }
    }
    
    sayHelloTo("Mathilde", repeat: 3)

On note, dans cet exemple, que le nom de paramètre repeat est à la fois dans l’appel et à l’intérieur de la méthode, mais aussi que Swift hérite de principes de son prédécesseur puisque le premier paramètre n’est pas nommé. Il est toujours explicité grâce au nom de la méthode.

Cependant, si l’utilisation des noms externes de paramètres tels qu’on le connaissait en Objective-C n’est plus obligatoire, elle reste utile selon le cas.
La documentation de Swift propose cet intérêt aux noms externes :

“The use of external parameter names can allow a function to be called in an expressive, sentence-like manner, while still providing a function body that is readable and clear in intent.”

On peut, par exemple, vouloir utiliser un nom externe pour le premier paramètre d’une méthode, si on ne supporte vraiment pas l’absence de nom pour celui-ci lors d’un appel.

    func sayHelloTo(name name: String)
    {
	    print("Hello  \(name) !")
    }
    sayHelloTo(name: "Mathilde")

Ici, le nom du paramètre est doublé mais garde le même nom, car il est clair à la fois pour l’appel et à l’intérieur mais, dans d’autres cas, on peut vouloir utiliser un autre nom afin d’apporter un peu plus de lisibilité :

    func sayHelloTo(name: String, repeat iterations: Int) {
      for _ in 1...iterations {
          print("Hello \(name)")
      }
    }
    
    sayHelloTo("Mathilde", repeat: 3)

Dans le cas contraire, si on souhaite omettre un nom externe, par exemple dans un constructeur, on peut le surcharger avec un underscore :

    class Point
    {
	    let x: Int
	    let y: Int
	    
	    init(_ x: Int, _ y: Int) 
		{
	      self.x = x
	      self.y = y
	    }
    }
    
    Point(0,0)
 

On se rapproche dans ce cas de la syntaxe du C# et du Java, ce qui peut être un avantage pour débuter, bien que le nommage explicite des paramètres soit très guidé par l’autocompletion dans XCode et le compilateur.

Swift va bientôt souffler sa 2ème bougie, et même si le langage est encore très jeune, il bouscule beaucoup de choses. Il est en effet open source depuis décembre 2015 et, avec les changements que cela implique, la communauté est mise à contribution pour décider (du moins en partie) de l’avenir de Swift. Et il y a un rapport direct avec le sujet de cet article, que nous allons voir tout de suite.

Swift 2.2 et Swift 3.0 : il est temps de revoir le nommage des paramètres

Avec l’arrivée (toute fraîche) de Swift 2.2 et les précisions concernant la version 3.0, Apple a communiqué sur nombre de changements qui vont avoir lieu dans le langage. Pour la version 2.2, quelques modifications sont apportées, mais sans grand impact. C’est dans la version 3.0 qu’apparaîtra un point très demandé et donc attendu. Voyons tout cela en détails.

Le choix des noms des paramètres est plus permissif

Uncle-Scrooge-McDuck-image-uncle-scrooge-mcduck-36758751-1024-768
Plus de noms de paramètres peuvent être utilisés : pour la version 2.2 de Swift, Apple rend possible l’utilisation de mots comme repeat comme nom d’argument. Cela peut paraître anodin, mais étant donné que “repeat” est un mot-clé du langage, jusqu’à présent il fallait soit choisir un autre nom, soit écrirerepeat. Et comme il est bien connu que le développeur se doit d’être feignant, ce changement va permettre de gagner du temps.

Voici un exemple de ce qu’il est possible de faire depuis quelques jours :

    
    func sayHelloTo(name: String, repeat repeatCount: Int) {
        for _ in 0 ..< repeatCount {
             print("Hello  \(name) !")
        }
    }
    sayHelloTo("Taylor", repeat: 5)

Disparition du mot clé var dans les paramètres

Les paramètres annotés avec var deviennent dépréciés. Le mot-clé var était utilisé pour spécifier que le paramètre pouvait être modifié à l’intérieur de la méthode. Mais il était très peu utilisé et était souvent confondu avec le mot-clé inout.

Ci-dessous un exemple d’utilisation du var, valable jusqu’à Swift 2.1 :

    func sayHelloTo(var name: String) {
	    name = name.uppercaseString
	    print("Hello  \(name) !")
    }

L’utilisation des paramètres externes dans les API Guidelines (Swift 3.0)

Pour revenir sur l’utilisation des paramètres externes, il est intéressant de souligner leur intérêt, car avec l’évolution de Swift par et pour les développeurs, on découvre de nouvelles façons de nommer les méthodes et de tirer parti des paramètres externes.
Par exemple, quand avant une méthode s’écrivait :

removeAtIndex(index: Int) -> Element

Elle se retrouve sous cette forme :

remove(at index: Int) -> Element

Cet exemple n’en est qu’un parmi tant d’autres, et la page Github regroupant les différences d’API de la standard library est intéressante à parcourir pour voir dans quelle direction se dirige Swift.

Le nom du premier paramètre d’une méthode devient obligatoire (Swift 3.0)

Depuis les débuts d’Objective-C, les développeurs souhaitant développer des applications pour Apple devaient changer leurs habitudes d’autres langages pour s’adapter à la syntaxe particulière du nommage de paramètres, le plus gros travail concernant la question du premier paramètre pour adapter le nom de la méthode. Mais cette vérité prendra bientôt fin! La nouvelle est tombée il y a quelques jours : la proposition d’Erica Sadun de rendre obligatoire le nom du premier paramètre a été acceptée et sera incluse dès la version 3.0 de Swift !
D’ici peu, le nom des paramètres sera donc obligatoirement visible et ce, quel que soit le paramètre ou le cas dans lequel on se place.

Hip hip hip hourra pour Erica Sadun !

Conclusion

Nous avons vu, au travers de cet article, le fonctionnement du nommage des paramètres de fonctions/méthodes dans le cadre d’applications écrites en Objective-C ou Swift, et les évolutions de sa syntaxe. Avec au départ quelques défauts, Apple a su s’adapter aux souhaits des développeurs, pour arriver d’ici quelques mois à un nommage des paramètres, certes toujours un peu verbeux, mais cohérent et beaucoup plus developer-friendly.

Nombre de vue : 481

AJOUTER UN COMMENTAIRE