Nous maîtrisons de nouveaux langages de programmation, en nous appuyant sur les acquis

Bonjour chers collègues.



Instantané de Jenny Marvin de Unsplash

Aujourd'hui, nous avons préparé pour vous une traduction d'un article sur les similitudes fondamentales de nombreux langages de programmation utilisant Ruby et C # comme exemple. Nous espérons que les idées du respecté Severin Peres aideront beaucoup d'entre vous à commencer rapidement à apprendre un nouveau langage de programmation, et les choses iront avec beaucoup de sens et de plaisir.

Ce qui n'enlève rien au programmeur - il n'arrête jamais d'apprendre. Vous pouvez avoir une langue préférée, ou un framework, ou une bibliothèque, mais il ne fait aucun doute que vous ne pouvez pas faire exclusivement avec eux. Vous pouvez aimer JavaScript, mais le projet sur lequel vous travaillez actuellement peut nécessiter Python. Vous pouvez être adepte de Perl, mais la base de code de votre entreprise peut être écrite en C ++. Pour un développeur débutant, l'idée d'apprendre une nouvelle langue peut sembler décourageante, surtout si des dates butoirs arrivent. Ce sont de mauvaises nouvelles. Cependant, il y en a une bonne: apprendre une nouvelle langue n'est généralement pas si difficile. Si nous prenons les modèles mentaux existants comme base, alors vous verrez que l'apprentissage d'une nouvelle langue est fondamentalement une extension des connaissances existantes et ne fonctionne pas à partir de zéro.

Qu'ont-ils en commun


La plupart des langages de programmation sont fondamentalement basés sur le même ensemble de principes clés. L'implémentation est différente, mais il n'y a guère deux langues si différentes qu'il ne sera pas possible de faire des parallèles entre elles. Afin d'apprendre et de comprendre une nouvelle langue, la chose la plus importante est d'identifier à quoi elle ressemble comme vous le savez déjà, puis d'acquérir de nouvelles connaissances, en élargissant votre compréhension de celle-ci quand / si nécessaire. Prenons par exemple les types de données et les variables. Dans chaque langue, il existe un moyen de définir et de stocker les données - uniformément tout au long du programme. Par conséquent, lorsque vous apprenez une nouvelle langue, vous devez d'abord comprendre comment les variables sont définies et utilisées ici. Prenons deux langages différents comme exemple: Ruby interprété avec typage dynamique et C # compilé avec typage statique.

my_int = 8 my_decimal = 8.5 my_string = "electron" puts "My int is: #{my_int}" puts "My float is: #{my_decimal}" puts "My string is: #{my_string}" 

Un exemple similaire:

 using System; public class Program { public static void Main() { int myInt = 8; double myDecimal = 8.5; string myString = "electron"; Console.WriteLine("My int is: {0}", myInt); Console.WriteLine("My float is: {0}", myDecimal); Console.WriteLine("My string is: {0}", myString); } } 

Supposons que vous êtes un développeur Ruby expérimenté et que vous souhaitez apprendre le C #. Voici des extraits de code, dans l'un desquels vous pouvez facilement reconnaître Ruby. Là, il vous suffit de définir plusieurs variables et de les afficher dans la console. Faites maintenant attention au deuxième fragment. Apprenez-vous quelque chose? La syntaxe est différente, mais il ne fait aucun doute que le second code fonctionne un peu comme le premier. L'opérateur = est rencontré plusieurs fois, ce qui est probablement frappant comme symbole des opérations d'affectation. Ensuite, un certain Console.WriteLine() est appelé, ce qui implique que les valeurs seront affichées dans la console. Il y a aussi quelques lignes ici qui semblent utiliser l'interpolation pour composer des messages. Sur le plan conceptuel, il n'y a rien de particulièrement surprenant ici - affectation, interpolation, sortie vers la console, toutes ces opérations sont déjà connues de vous en travaillant avec Ruby.

Vous pouvez comprendre le deuxième fragment de code sans aucune connaissance de C #, mais il est certainement possible d'étendre votre modèle mental. Par exemple, pourquoi tout le monde s'enveloppe-t-il dans la méthode Main() ? Quels sont ces mots clés int , double et string ? Avec cela, la formation commence. Vous comprenez déjà en termes généraux ce qui se passe ici (affectation, interpolation, sortie), il est maintenant temps de passer aux détails:

  • Main() : Ayant un peu plus profondément dans la situation, nous découvrons que la méthode Main() est le point d'entrée à partir duquel le programme démarre. Nous savons maintenant que dans tous les programmes C #, nous avons besoin de la méthode Main ().
  • Variables: dans la première partie de notre fragment en C #, une sorte d'affectation se produit définitivement. Compte tenu de la nomenclature, vous devinez probablement que le mot clé int signifie une variable entière, double est un nombre à virgule flottante double précision et string est une variable chaîne. Presque immédiatement, vous vous rendez compte qu'en C #, contrairement à Ruby, le typage statique des variables est requis, car les variables sont déclarées différemment pour différents types de données. Après avoir lu la documentation, vous comprendrez à quel point elle est différente.
  • Console.WriteLine() : Enfin, en exécutant le programme, vous verrez que Console.WriteLine() affiche les valeurs dans la console. À partir de Ruby, vous savez que puts est une méthode de l'objet global $stdout , et si vous consultez la documentation de Console.WriteLine() , vous constaterez que Console est une classe de l'espace de noms System et WriteLine() est la méthode définie dans ce classe. Cela ressemble non seulement à des put, mais suggère également que C #, comme Ruby, est un langage orienté objet. Ici, vous avez un autre modèle mental qui vous aidera à tracer de nouveaux parallèles.

L'exemple ci-dessus est très simple, mais même un certain nombre de conclusions importantes peuvent en être tirées. Vous avez déjà appris qu'un programme C # nécessite un point d'entrée bien défini, que ce langage est typé statiquement (contrairement à Ruby) et orienté objet (comme Ruby). Vous l'avez compris, parce que vous imaginez déjà ce que sont les variables et les méthodes, puis vous avez élargi ces modèles mentaux, les enrichissant avec le phénomène de typification.

Rechercher des différences


Commencer à essayer de lire et d'écrire du code dans un nouveau langage, la première chose dont vous avez besoin pour savoir ce que les choses sont déjà connues et peuvent servir de base à l'apprentissage. Ensuite, passez aux différences. Revenons à notre transition de Ruby à C # et regardons quelque chose de plus compliqué.

 particles = ["electron", "proton", "neturon"] particles.push("muon") particles.push("photon") particles.each do |particle| puts particle end 

Dans ce fragment Ruby, nous définissons un tableau appelé particles , qui contiendra plusieurs lignes, puis utiliser Array#push pour lui ajouter quelques lignes supplémentaires, et Array#each pour parcourir le tableau et sortir chaque ligne individuelle vers la console. Mais comment faire de même en C #? Un peu sur Google, nous constatons que C # a tapé des tableaux (la frappe ne devrait plus vous surprendre, compte tenu de ce que vous avez appris plus tôt), et il existe également une méthode SetValue qui ressemble légèrement à push , mais prend la valeur et la position dans l'index comme paramètres. Dans ce cas, la première tentative de réécriture du code Ruby en C # peut entraîner ceci:

 using System; using System.Collections.Generic; public class Program { public static void Main() { string[] particles = new string[] { "electron", "proton", "neturon" }; particles.SetValue("muon", 3); //    ( 11):      particles.SetValue("photon", 4); foreach (string particle in particles) { Console.WriteLine(particle); } } } 

Malheureusement, ce code lèvera une Run-time exception lorsque vous essayez d'utiliser SetValue pour ajouter une nouvelle valeur au tableau. Encore une fois, nous regardons la documentation et découvrons que les tableaux en C # ne sont pas dynamiques et doivent être initialisés soit immédiatement avec toutes les valeurs, soit avec une indication de la longueur. Essayez à nouveau de reproduire le code Ruby, réfléchissez à ceci et obtenez l'option suivante:

 using System; using System.Collections.Generic; public class Program { public static void Main() { string[] particles = new string[] { "electron", "proton", "neturon", null, null }; particles.SetValue("muon", 3); particles.SetValue("photon", 4); foreach (string particle in particles) { Console.WriteLine(particle); } } } 

Cet extrait reproduit vraiment toutes les fonctionnalités du code source Ruby, mais avec une grande extension: il affiche simplement les mêmes valeurs à la console. Si vous examinez attentivement les deux fragments, un problème est rapidement découvert: dans un fragment en C # dans le tableau de particules, il ne peut y avoir plus de 5 valeurs, tandis que dans un fragment en Ruby, ils sont autorisés autant que vous le souhaitez. Ensuite, il devient clair que les tableaux en Ruby et C # sont fondamentalement différents: le premier a une taille dynamique, tandis que le second n'en a pas. Pour reproduire correctement la fonctionnalité d'extrait de Ruby en C #, vous avez besoin de plus de ce code:

 using System; using System.Collections.Generic; public class Program { public static void Main() { List<String> particles = new List<String>(); particles.Add("electron"); particles.Add("proton"); particles.Add("neutron"); particles.Add("muon"); particles.Add("photon"); foreach (string particle in particles) { Console.WriteLine(particle); } } } 

Cela utilise la structure de données List pour collecter dynamiquement des valeurs. Dans ce cas, nous reproduisons en fait le code Ruby original en C #, mais, plus important encore, ici, nous pouvons apprécier la différence clé entre les deux langages. Bien que le terme «tableau» soit utilisé dans les deux langues et qu'il puisse sembler que ces tableaux sont identiques, dans la pratique, ils sont très différents. Voici encore une chose qui aide à élargir le modèle mental, à mieux comprendre ce qu'est un «tableau» et comment il est organisé. En C #, un tableau en tant que structure de données peut convenir ou non dans des situations où, dans Ruby, vous auriez recours à des tableaux; nous parlons de situations où le redimensionnement dynamique d'un tableau est critique. Maintenant, vous devez vous en occuper à l'avance et réfléchir à votre code en conséquence.

Revenir aux principes clés


Il est très pratique de commencer à apprendre de nouvelles langues, en explorant leurs similitudes et leurs différences par rapport aux langues déjà connues; cependant, dans certains cas, il est préférable de commencer par des principes universels. Ci-dessus, nous avons conclu logiquement que C # était un langage orienté objet lorsque nous travaillions avec une classe intégrée et l'une de ses méthodes, System.Console.WriteLine() , avec laquelle nous avons effectué une action. Il est logique de supposer qu'en C #, comme dans d'autres langages orientés objet, il existe un mécanisme pour définir une classe et en instancier des objets. Il s'agit d'un principe de base de la programmation orientée objet, vous pouvez donc avoir peu de doute sur l'exactitude de notre hypothèse. Voyons d'abord à quoi pourrait ressembler cette opération dans le langage Ruby familier.

 class Element attr_accessor :name, :symbol, :number def initialize(name, symbol, number) self.name = name self.symbol = symbol self.number = number end def describe puts "#{self.name} (#{self.symbol}) has atomic number #{self.number}." end end hydrogen = Element.new("Hydrogen", "H", 1) hydrogen.describe 

Nous avons ici une classe Element simple, dans laquelle il existe une méthode constructeur pour accepter des valeurs et les affecter à des objets instanciés, un ensemble de méthodes d'accès pour définir et recevoir des valeurs, ainsi qu'une méthode d'instance pour sortir ces valeurs. Dans ce cas, les concepts clés sont l'idée d'une classe, l'idée d'une méthode constructeur, l'idée de getters / setters et l'idée d'une méthode d'instance. Pour revenir à nos idées sur ce qui peut être fait dans les langages orientés objet, nous verrons comment faire de même en C #.

 using System; public class Program { public static void Main() { Element hydrogen = new Element("Hydrogen", "H", 1); hydrogen.Describe(); } public class Element { public string Name { get; set; } public string Symbol { get; set; } public int Number { get; set; } public Element(string name, string symbol, int number) { this.Name = name; this.Symbol = symbol; this.Number = number; } public void Describe() { Console.WriteLine ( "{0} ({1}) has atomic number {2}.", this.Name, this.Symbol, this.Number ); } } } 

Après avoir étudié ce fragment en C #, nous voyons qu'en fait, il n'est pas si différent de la version Ruby. Nous définissons la classe, en utilisant le constructeur, spécifiez comment la classe va instancier les objets, définissons les getters / setters et déterminons la méthode d'instance que nous appellerons dans les objets créés. Naturellement, les deux fragments sont d'aspect assez différent, mais pas de la manière la plus inattendue. Dans la version C #, nous utilisons this pour faire référence à l'objet instancié, tandis que dans Ruby, nous utilisons self pour cela. La version C # est tapée à la fois au niveau de la méthode et au niveau des paramètres, tandis que dans Ruby, ce n'est pas le cas. Cependant, au niveau des principes clés, les deux fragments sont presque identiques.

En développant ce sujet, nous pouvons considérer l'idée d'héritage. Il est connu que l'héritage et le sous-classement sont les points clés de la programmation orientée objet, il est donc facile de comprendre qu'en C # cela se fait avec le même succès qu'en Ruby.

 class Element attr_accessor :name, :symbol, :number def initialize(name, symbol, number) self.name = name self.symbol = symbol self.number = number end def describe puts "#{self.name} (#{self.symbol}) has atomic number #{self.number}." end end class NobleGas < Element attr_accessor :category, :type, :reactivity def initialize(name, symbol, number) super(name, symbol, number) self.category = "gas" self.type = "noble gas" self.reactivity = "low" end def describe puts "#{self.name} (#{self.symbol}; #{self.number}) is a #{self.category} " + "of type #{self.type}. It has #{self.reactivity} reactivity." end end argon = NobleGas.new("Argon", "Ar", 18) argon.describe 

Dans la version Ruby, nous définissons une sous-classe de NobleGas qui hérite de notre classe Element ; son constructeur utilise le super mot-clé, qui étend le constructeur de la classe parente et remplace ensuite la méthode d'instance de describe pour définir un nouveau comportement. La même chose peut être faite en C #, mais avec une syntaxe différente:

 using System; public class Program { public static void Main() { NobleGas argon = new NobleGas("Argon", "Ar", 18); argon.Describe(); } public class Element { public string Name { get; set; } public string Symbol { get; set; } public int Number { get; set; } public Element(string name, string symbol, int number) { this.Name = name; this.Symbol = symbol; this.Number = number; } public virtual void Describe() { Console.WriteLine ( "{0} ({1}) has atomic number {2}.", this.Name, this.Symbol, this.Number ); } } public class NobleGas : Element { public string Category { get; set; } public string Type { get; set; } public string Reactivity { get; set; } public NobleGas(string name, string symbol, int number) : base(name, symbol, number) { this.Category = "gas"; this.Type = "noble gas"; this.Reactivity = "low"; } public override void Describe() { Console.WriteLine ( "{0} ({1}; {2}) is a {3} of type {4}. It has {5} reactivity.", this.Name, this.Symbol, this.Number, this.Category, this.Type, this.Reactivity ); } } } 

À première vue, alors que nous ne savions toujours rien de C #, cette dernière liste peut sembler intimidante. La syntaxe n'est pas familière, certains mots clés et codes étranges ne sont pas organisés comme nous le faisions auparavant. Cependant, si nous considérons ce code du point de vue des principes de base, la différence n'est pas si importante: nous avons juste ici une définition de classe, un ensemble de méthodes et de variables et une série de règles pour instancier et utiliser des objets.

TL; DR


Apprendre une nouvelle langue peut être extrêmement difficile si vous le faites à partir de zéro. Cependant, la plupart des langages de programmation sont basés sur les mêmes principes de base, entre lesquels il est facile de faire des parallèles, de remarquer des différences importantes et d'appliquer dans de nombreux langages. En essayant une nouvelle langue sur des modèles mentaux existants, vous pouvez trouver où elle ne diffère pas des langues déjà étudiées et où vous avez vraiment besoin de clarifier quelque chose. En étudiant de plus en plus de langues au fil du temps, vous développez vos modèles mentaux et ces améliorations sont de moins en moins nécessaires - vous reconnaîtrez diverses implémentations dans différentes langues de la feuille.

Source: https://habr.com/ru/post/fr422869/


All Articles