汝、SLAPを愛せよ。

<span style="font-size: 200%">SLAP</span>という言葉があります。<br>
<b>Single Level of Abstraction Principle</b>の略ですが、`DRY`,`YAGNI`と比べると認知度が低く感じます。<br>
ぜひ知ってほしいことなので紹介します。
<br>

<!-- more -->

#SLAPとは

まず、ソースコードは低水準なもの、高水準なものがあります。<br>
この水準を揃えたコードを書きましょう、というのがSLAPの基本的考え方になります。<br>
水準が同じ処理を１まとめにして関数化し、その関数をより上の水準の関数から呼び出すような階層構造にすることで、全体の動きが俯瞰しやすくなります。<br>
<br>
## 高水準なコードとは
オブジェクト指向言語であれば、<b>Public</b>で外部公開されたメソッドがこれにあたります。
例えば、ボタンをクリックした時にコールされる関数やメソッド等になります。<br>
ユーザー側、外部向けのコードというイメージです。<br>

## 低水準なコードとは
オブジェクト指向言語であれば、<b>Private</b>で非公開のメソッドがこれにあたります。
実際の処理(ロジック)、計算式、APIの利用やファイルの読み書き、インターフェース等になります。<br>
より内部的なコードというイメージです。<br>

##大切なこと
ここで、高水準、低水準と２つを説明していますが、実際のプログラミングを２つの水準に分けることは非常に難しく
むしろ無理に２つの水準に分けた結果読みにくくなってしまうかもしれません。<br>
大切なのは<b>水準を作ってそれを揃える</b>ことなので、２つだけではなく３つ、４つ、あっても構いません。<br>
<b>プロダクティブ・プログラマ</b>では高水準、低水準の２つしか説明してませんが、より実用的にするのであれば、
高水準、低水準ではなくレイヤの階層構造をイメージしてください。<br>
<br>
例えば、以下のように分けていきます。<br>
 
 * ユーザーの操作を受ける最上位レイヤ
 * 最上位レイヤが持つモデルクラスの公開メソッドとなる第２レイヤ
 * モデルクラスの公開メソッド内で呼び出される実際の処理の第３レイヤ
 * 実際の処理の中で呼び出されるライブラリの関数となる第４レイヤ

<br>
繰り返しますが、目的は<b><span style="color: #ff5252">水準を作ってそれを揃える</span></b>ことで、２つの水準にわけることではありません。<br>
<br>

# 類似したプログラミングの原則
<b>実装パターン</b>という本では「<span style="color: #1464b3"><b>宣言型の表現</b></span>」という言葉があり、これはコードを宣言的に書きましょうという原則で、
ソースコードはできるだけ条件分岐や繰り返しがない方がわかりやすくなる、ということです。<br>
<br>
例えば、

1. ○○のデータを△△にコピーする
2. △△を□□を使って解析する
3. □□を◇◇にアップロードする

というビジネスロジックがあり、それぞれをLogic1, Logc2, Logic3とします。<br>
それを関数にする場合、以下のようにすれば読みやすくなる、ということです。<br>

```ruby
def bizlogic
  Logic1
  Logic2
  Logic3
end
```

個人的にですが、これとSLAPは近いものが有ると思っています。<br>
何故かと言うと、処理の水準を揃えようとするとそれぞれの水準で別の関数になりますので、それを１つ上の水準で利用すると<br>
自ずと宣言型の表現に近い形になると思います。
<br>
ただし、必ずしも高いの水準で宣言型の表現ができるわけではなく、<br>
最も高い水準のボタンクリック時にコールされるイベントでも、チェックボックスがチェックされている・されていないで処理を変える事はあります。<br>

```ruby
def button_click
  if checkbox = true 
    foo
  else
    bar
  end
end
```

なので<b><span style="color: #ff5252">できるだけ</span></b>条件分岐、繰り返しを使わないというわけです。
<br>

#メリット

* 高水準で宣言的に書かれた関数が処理の要約となるため読みやすくなる
* 処理の階層が俯瞰でき、構造が理解しやすくなる

#どうすればいいの？
以下の３つを意識すればSLAPに沿ったコードが書けるようになります。

#### 複合関数とロジック関数（オブジェクト指向ならメソッド）をはっきり分けること<br>
##### 複合関数とは
他の関数を呼び出すのみで自分自身は計算式などの処理を関数を<b>集合関数</b>と言います。<br>
以下はbar関数とbaz関数を呼び出す複合関数fooの例です。

```ruby
def foo
  bar
  baz
end
```

この複合関数がソースコードの要約として読めるようになります。<br>
複合関数はできるだけ<b>宣言型の表現で</b>書くようにすることでよりわかりやすくなります。
<br>
この複合関数で呼び出す関数・メソッド名はわかりやすい命名にすることが重要です。<br>
もしわかりにくい名前にしてしまうと、<b>要約として意味をなさなくなります。</b>
<br>
また、この書き方は`Composed Method`というデザインパターンとなっています。<br>
##### ロジック関数とは
実際の処理を書く関数になります。<br>
このロジック関数は、１つだけの処理を実装し、複数の処理は実装しないようにします。<br>
より下の水準のロジック関数を呼び出すことは構いませんが、複合関数は呼び出さないようにします。<br>
<br>
#### Publicなメソッドで実装の詳細を書かないこと
Publicなメソッドは、基本的に集合関数にします。<br>
なぜかというと、後から他の所から利用したいと思い、コードを読んだ時に処理の内容を理解しやすくするためです。<br>
<br>
なのでPublicなメソッドはわかりやすくするため詳細なロジックは書かないようにしましょう。<br>
詳細なロジックは隠蔽されたprivateメソッドで書くようにするべきです。<br>

#### 階層構造を考え、ロジック関数から複合関数を呼び出す処理は行わないこと
ロジック関数は、関数の階層構造の末端と考えます。<br>
もし、ロジック関数から複合関数を呼び出すような処理が必要であれば、<br>
そのロジック関数を呼び出す複合関数でその複合関数を呼び出すようにしたほうが階層がわかりやすくなります。<br>
<br>
ロジック関数で複合関数を呼び出してしまうと、別の水準の関数を使うことになってしまい、階層構造が崩れます。<br>
<br>
#### １つの関数が複数の水準を持たないこと
例えば、１つの関数内に他の関数を呼び出し、ロジックも書くような事をしてしまうと、<br>
複数の水準をもつことになり次にどうなるかがわかりにくくなります。<br>
<br>
例えば、以下のような例です。

```ruby
def func1
  logic1
  logic2
  
  #Logic3 
  if foo
    bar = 1
  end
   
   baz = bar+1
  ...
end
```

logic1, logic2, logic3は１つ下のレイヤの処理で、logic1とlogic2は別の関数で処理しているのにも関わらず,<br>
logic3はこの関数内で唐突に下のレイヤの処理が書かれています。<br>
こう言うパターンが１つの関数が複数のレイヤを持つ状態で、<br>
ビジネスロジックを追いかけるだけなのに１つ１つの計算式を見なくてはいけなくなります。<br>
<br>

#より上を目指すために
各ロジック関数は柔軟に使え、再利用しやすいように部品化しておくことで、他の高レベルレイヤでも使えるようになります。<br>
また、コードの重複を防げるようになるので`DRY`なコードになります。<br>

#最後に
ソフトウェアが大きくなると、ソースコードの階層構造をしっかり作っておかないと読みにくくなり、メンテナンスが難しくなってしまいます。<br>
また、コードを読む時に`要約`がないと、読むのに時間がかかってしまいます。<br>
<br>
ソフトウェアは何年使われるか予測するのが難しく、自分が理解できていても自分がその製品の担当から外れた時に他のプログラマがコードを読んで<br>
<span style="color: #ff5252"><b>「誰だこんな読みにくいコードを書いたのは！」</b></span>と内心怒り心頭になったりします。<br>
<span style="font-size: 75%"><span style="color: #0000cc">
自分のこと
</span></span>
<br>
<br>
自分が作ったものに対して誰かが怒っていると知ったらちょっと落ち込みますよね。<br>
逆にあんな読みやすいコード書いてくれてありがとう！と感謝してたら嬉しくなります。<br>
<br>
他の人に感謝されるようなコードを書いていこう！<br>
<span style="font-size: 80%"><span style="color: #2196f3">そのほうが精神衛生上いいし</span></span>
<br>


#参考文献
プリンシプルオブプログラミング　http://amzn.asia/dYUCdR9 
実装パターン http://amzn.asia/8xfUnGs 
プロダクティブ・プログラマ http://amzn.asia/29KY7X0 
リファクタリング http://amzn.asia/aHo1Gkv