Tbpgr Blog

Recruiting Operations tbpgr(てぃーびー) のブログ

書籍 Productive Programmer | SLAPで抽象度を揃えて読みやすいコードにする

パンくず

書籍 Productive Programmer
SLAPについて

概要

SLAPについて説明します。

SLAPとは?

Single Level of Abstraction Principleの略。
コーディングにおいて、抽象度の統一を行う原則のこと。

イメージとしては部、章、節、項のように綺麗に
階層化された書籍が読みやすいようにコードも読みやすくなる。

publicメソッド

抽象度を揃えて出来るだけシンプルに。
publicメソッドには処理の概要となるprivateメソッド
呼び出しが並び、メソッド名を読むだけで処理の概要をつかめるようにするのがよい。

難しいロジックはprivateメソッドにすることで
処理の流れを読み取りやすくなる。

好ましくないコード

様々な抽象度の処理が混在している

class CodeGenerator
  # テンプレートを置き換えるコード生成処理をイメージ
  def generate(class_name, method_name, output_path)
    template_file = File.new("test.rb")
    template = template_file.read
    template = replaceText(template, "$class_name", class_name)
    template = replaceText(template, "$method_name", method_name)
    output = open(output_path, "a")
    output.puts template
    output.close
  end
  
  private
  def replaceText(template, from_word, to_word)
    template.gsub(from_word, to_word)
  end
end

class_name = "classA"
method_name = "methodA"
output_path = 'C:\kt\txt\output.txt'
CodeGenerator.new.generate(class_name, method_name, output_path)

SLAPを守ったコード

「部」「章」「節」的階層のコードになっている

publicメソッド
  ファイルを取得
  ファイルの内容を読み取り
  テンプレート部分に値を置換
    クラス名を置換
    メソッド名を置換
  結果をファイル出力
# encoding: Windows-31J
require "pp"

# $class_name
# $method_name

class CodeGenerator
  # テンプレートを置き換えるコード生成処理をイメージ
  def generate(class_name, method_name, output_path)
    template_file = get_template_file("test.rb")
    template = get_template_text(template_file)
    template = replace_template(template, class_name, method_name)
    output_file(template, output_path)
  end
  
  private
  def get_template_file(template_path)
    File.new(template_path)
  end
  
  def get_template_text(template_file)
    template_file.read
  end
  
  def replace_template(template, class_name, method_name)
    template = set_class_name(template, class_name)
    template = set_method_name(template, method_name)
  end
  
  def output_file(template, output_path)
    output = open(output_path, "a")
    output.puts template
    output.close
  end
  
  def set_class_name(template, class_name)
    replaceText(template, "$class_name", class_name)
  end
  
  def set_method_name(template, method_name)
    replaceText(template, "$method_name", method_name)
  end
  
  def replaceText(template, from_word, to_word)
    template.gsub(from_word, to_word)
  end
end

class_name = "classA"
method_name = "methodA"
output_path = 'C:\kt\txt\output.txt'
puts CodeGenerator.new.generate(class_name, method_name, output_path)