Mémorandum pour nettoyer le code Ruby

Il est difficile d'écrire du code proprement

Je ne le remarque pas quand je l'écris, et même si je le regarde après avoir fini de l'écrire, il est difficile de démonter et de reconstruire le code que j'ai écrit une fois que j'y ai pensé. Cela nécessite une approche différente pour écrire du code lors de la reconstruction. L'endroit où j'ai pensé que c'était le cas et réécrit le code avec une tête vide est la montagne. Cette fois, j'écrirai quelques modèles que j'ai remarqués dans une partie aussi réécrite. C'est un mémorandum basé sur ma propre expérience.

Presque le même traitement est inclus dans l'expression conditionnelle

En fait, le traitement que vous souhaitez effectuer est le même, mais il existe deux types de contenus de paramètres qui sont passés en arguments, on_total et on_this_month, et si vous détectez l'un de ces deux, vous vouliez inclure le traitement à trier. Le premier que j'ai écrit est ci-dessous.

bad_1.rb


def self.ascend_checkins(param, hash)
  if param == "on_total"
    hash.sort_by { |k,v| -v["total"] }.to_h
  elsif param == "on_this_month"
    hash.sort_by { |k,v| -v["month"] }.to_h
  end
end

Pour la raison mentionnée ci-dessus, le même processus de tri a été inclus, modifiez-le comme suit.

mod_1.rb


  def self.ascend_checkins(hash, param)
    key_of = {"on_total" => "total", "on_this_month" => "month"}
    value = key_of[param]

    raise "unknown param" if !value
    hash.sort_by { |k,v| -v[value] }.to_h
  end

Puisqu'il n'y a que deux paramètres, préparez un hachage, recevez le paramètre, jugez la valeur qui lui correspond par la valeur booléenne, et si c'est vrai, supprimez le processus en exécutant le processus.

De nombreuses variables temporaires

Voici le processus d'extraction de l'ID utilisateur sous forme de chaîne de caractères, en comptant le nombre de celui-ci et en le convertissant en hachage. C'est devenu un processus avec de nombreuses variables temporaires lors de la préparation d'un tableau vide.

bad_2.rb


def self.get_monthly_count(ids, users)
    uids = []
    ids.each do |id|
      uids.push id.uid.to_s
    end

    uid = {}
    count = 0
    users.each do |user|
      uid[user] = uids[count]
      count += 1
    end
    uid.to_h
  end

C'est rangé en une seule ligne, dans le cas de Ruby.

mod_2.rb


def self.get_monthly_count(ids, users)
  users.zip(ids.map{ |id| id.uid.to_s }).to_h
end

Tout d'abord, si vous utilisez la méthode map, vous n'avez besoin que d'une seule ligne pour l'extraire en tant que chaîne de caractères et la recréer sous forme de tableau. Si vous créez un tableau vide et écrivez un traitement à l'aide d'index, il semble que vous puissiez écrire du code propre depuis le début si vous pensez utiliser ce type de méthode en premier. Après cela, j'utilise la méthode zip pour créer un tableau de paires et enfin le hacher.

motif zip

C'est une méthode qui peut combiner des éléments d'un tableau comme un mandrin.

zip.rb


array_keys = ["Tom", "Bob", "Joge"]
array_values = [167, 156, 181]

zipped = array_keys.zip(array_values)
p zipped # [["Tom", 167], ["Bob", 156], ["Joge", 181]]

hash = zipped.to_h

p hash # {"Tom"=>167, "Bob"=>156, "Joge"=>181}

De nombreuses variables temporaires

Il y en a trois, user_names, uid et users, mais vous n'avez pas besoin de les créer comme ça.

bad_3.rb


def self.get(check_ins)
  user_names = []
    check_ins.each do |check_in|
      uid = check_in.uid
      users = community_number_collection.document(uid).get
      user_names.push users.data[:nickname]
    end
  user_names
end

Si un tableau vide est créé, il sera traité à l'aide de map, et il sera rassemblé en une seule ligne sans créer de variables supplémentaires.

mod_3.rb


def self.get(check_ins)
  check_ins.map do |check_in|
    community_number_collection.document(check_in.uid).get.data[:nickname]
  end
end

Combinez carte et zip pour raccourcir

Combinez ceux mentionnés ci-dessus pour raccourcir le processus.

bad_4.rb


def self.get_total(merged_data, users)
    sum =  []
    merged_data.keys.each do |value|
      uid = merged_data[value]["uid"]
      sum.push self.where(uid: uid).count
    end
    sum
    total = {}
    count = 0
    users.each do |user|
      total[user] = sum[count]
      count += 1
    end
    total
  end

La carte et le zip le rendront beaucoup plus court. C'était aussi une découverte que le traitement de bloc entier était poussé dans une variable appelée sum. Le bloc est une expression, et il sera possible de l'attribuer.

mod_4.rb


def self.get_total(merged_data, users)
  sums = merged_data.keys.map do |key|
    self.where(uid: merged_data[key]["uid"]).count
  end
  users.zip(sums).to_h
end

Meilleur processus de calcul de hachage

Les hachages comptent les doublons et sont utiles pour l'agrégation. Mais plus c'est court, mieux c'est.

bad_5.rb


def self.get_this_month(check_ins)
    check = {}
    check_ins.each do |check_in|
      uid = check_in.uid.to_s
      uid_count = check[uid] || 0
      check[uid] = uid_count + 1
    end
    check.values.each do |value|
      value
    end
  end

Je n'ai pas utilisé de tableau vide cette fois, mais si vous mettez le processus d'extraction des éléments du tableau d'origine dans chacun, il est préférable de recréer le tableau souhaité avec la carte et de transformer ce tableau avec chacun. .. De plus, si vous utilisez la méthode par défaut, vous pouvez définir une fois toutes les valeurs sur 0.

mod_5.rb


def self.get_this_month(check_ins)
  check = {}
  check.default = 0
  check_ins.map{ |c| c.uid.to_s }.each do |uid|
    check[uid] += 1
  end
  check.values
end

Généralisation des fonctions

Avant le code ci-dessous, il y avait deux fonctions qui faisaient la même chose, sauf que les clés du hachage passé étaient différentes. Je l'ai mis ensemble dans une fonction abstraite. Après avoir préparé un tableau vide, déclarez un tableau vide avec la clé spécifiée (nested = {}), et dans chacun, vous pouvez avoir un hachage sans valeur pour la clé (nested [key] = {} ).

sample_1.rb


  def self.label_hash(hash_dictionary, keys)
    nested = {}

    keys.each do |key|
      nested[key] = {}
      hash_dictionary.each do |name, hash|
        nested[key][name] = hash[key]
      end
    end
    nested
  end

En tant que méthode d'appel, la méthode de regroupement des arguments dans un hachage est utilisée. Dans la fonction supérieure, les mots utilisés sont proches de l'abstrait, et dans l'appel inférieur, des mots à forte spécificité sont utilisés. Vous pouvez voir que les rôles sont clairement séparés par un nom.

sample_2.rb


labeled_totally_count = CheckIn.label_hash({
    "month" => zipped_monthly_count,
    "total" => zipped_totally_count
}, zipped_monthly_count.keys)

Résumé

Un autre problème avec l'écriture de code difficile à lire est que le nom que vous utilisez déjà est enraciné dans le monde de la programmation en tant que concept différent, de sorte qu'un ingénieur qualifié peut voir le code. Sachez qu'il peut souvent être rappelé à la fin, ce qui entraîne une mauvaise lecture, et par conséquent, le code que vous écrivez est souvent difficile à lire.

Recommended Posts

Mémorandum pour nettoyer le code Ruby
[Ruby] Code pour afficher le jour
AtCoder Beginner Contest 170 A, B, C jusqu'au rubis
[Ruby] Comment récupérer le contenu du double hachage
Un mémorandum pour atteindre le lieu qui démange pour Java Gold
Un mémorandum pour écrire un beau code
Un mémorandum du problème FizzBuzz
J'ai essayé d'écrire du code comme une déclaration de type en Ruby
(Ruby on Rails6) Créer une fonction pour modifier le contenu publié
Un mémorandum sur l'utilisation d'Eclipse
La route pour créer un jeu sonore 2
[Ruby] Des bases à la méthode inject
Étapes minimales pour configurer un environnement Ruby avec rbenv sur Ubuntu 20.04
[Ruby] Renvoie les caractères en forme de pyramide en fonction du nombre saisi
La route pour créer un jeu sonore 3
Configurez une interface graphique Java dans un thread séparé pour conserver le
La route pour créer un jeu sonore 1
Pourquoi le code était-il pénible à lire?
[Java: Memorandum] Jusqu'à ce que le code de saut de ligne CRLF soit changé en LF
03. J'ai envoyé une demande de Spring Boot à l'API de recherche de code postal
Jusqu'au lancement d'un conteneur Docker construit avec RedHat Quarkus
[Ruby] Envoyez une requête HTTP POST à l'API Web à l'aide de l'authentification OAuth
"Puzzle mathématique pour entraîner le cerveau du programme plus" _Q40 (code: Ruby) -> Rust inachevé
Comment trouver la cause de l'erreur Ruby
Faire une marge à gauche du TextField
Code pour échapper aux chaînes JSON en Java
L'histoire de l'introduction de la communication Ajax à Ruby
Définir l'heure de LocalDateTime à une heure spécifique
[Ruby] Je veux faire un saut de méthode!
Code utilisé pour connecter Rails 3 à PostgreSQL 10
[Ruby on Rails] Un mémorandum de modèles de mise en page
Comment écrire du code qui pense Ruby orienté objet
[Ruby] Comment générer une chaîne de caractères d'alphabet aléatoire
Nettoyer findViewById du code source avec DataBindingLibrary
Comment créer la blockchain la plus simple de Ruby
Je veux obtenir la valeur en Ruby
[Introduction à Ruby] Comment utiliser la méthode slice
La voie de la création d'un service Web (partie 1)
Introduction à Ruby 2
[Orienté objet] Un mémorandum qui fait de zéro le meilleur [Résumé du site qui a aidé à comprendre le concept]
Code d'écriture Ruby
Exemple de code pour attribuer une valeur dans le fichier de propriétés à un champ du type attendu
Notez que j'étais accro aux paramètres du projet Android d'IntelliJ IDEA
Une revue du code utilisé par les rails débutants
[Ruby] Liste de codes de base. Gardez les bases avec des exemples
[Introduction] Créer une application Ruby on Rails
Une brève introduction à terasoluna5, voir le texte ci-dessous
Comment exécuter l'application SpringBoot en tant que service
J'ai lu le code lisible, alors prends note
[Ruby] Générer un code QR concaténé avec rqrcode (Knowledge)
Un mémorandum de dépendance à Spring Boot2 x Doma2