14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アスペクト指向を簡単に調査。また、jsのメソッドへの処理の注入

Last updated at Posted at 2017-07-13

アスペクト指向とは何か。Wikipediaを抜粋すると以下だ。

アスペクト指向プログラミング(アスペクトしこうプログラミング、Aspect Oriented Programming、AOP)は、オブジェクト指向ではうまく分離できない特徴(クラス間を横断 (cross-cutting) するような機能)を「アスペクト」とみなし、アスペクト記述言語をもちいて分離して記述することでプログラムに柔軟性をもたせようとする試み。

個人な感想を言えば、処理が追えなくなるんじゃないの?という感想。

以下の記事も読んだ。
アスペクト指向プログラミング入門 http://postd.cc/intro-to-aop/

prototypeを使う頻度はめっきり減ったのは別として、はじめのPhoneクラスからあまりにひどいコードがでてきてちょっとビビる。
dialにlogなんて入れた瞬間に単体テストしづらくなるだけだろうに。この例だと依存がひどいだけで、単に処理を分散させて見づらくしただけに見える。

まあ、本筋ではないのでまとめると、どうやらAOPはある処理に対して前処理や後処理を後から機能を追加できるものと捉えれば良さそうだ。(ひどくいびつな捉え方であると言えるが、やっていることは似たようなものだ)

以下の記事も読んだ。
それにしても古い記事か飛ばし記事しかでないので、流行らなかったんだなという印象を受ける。

アスペクト指向プログラミングに関する十の神話
http://prg.is.titech.ac.jp/members/masuhara/papers/aop-myth.pdf

ここにある名前ベースの技術という指摘は尤もだと思う。

"ログを取るための技術だ"。たしかに、いくつか例も出てるが確かにログ以外に実際の利用は難しく思える。

以下の記事は、アスペクトまわりの用語がよくまとまっていてよかった。

時代が来るかも?アスペクト指向プログラミング, AspectJ言語とは何か - Qiita

やはり、例がログだった。

ここまで見てきて思ったのが、基本的に静的型付けのための技術であるように思える。
動的言語なら、特定のメソッドの前後に処理を追加なんて数行でできるからだ。

JSで前処理と後処理を追加する例を書いてみる。

はじめに単純にhelloを出力するメソッドhelloを用意する。
もうprototypeなんて書く機会があまりないけど、上記のコードに倣ってちょっとes5で書いてみる。

var A = function() {}
A.prototype.hello = function() {
  console.log('A: hello')
}

var a = new A()

a.hello()
// => A: hello

さて、このA: hello前後に処理を追加したい。
例なのでboforeafterを出力する。

以下の関数を用意する。
jsは第1級関数がサポートされてるので、単に関数をコピーして、前後に処理を挟んでやればいい。

function injectBeforeAfter(name, func) {
  if (func.prototype[name]) {
    var fn = func.prototype[name]
    func.prototype[name] = function() {
      console.log('before')
      fn.apply(func, arguments)
      console.log('after\n')
    }
  }
}

あとは、クラスAを渡せばhelloの呼び出しの前後に処理を注入できる。

var injectHello = injectBeforeAfter.bind(null, 'hello')

injectHello(A)

var a = new A()
a.hello()
//=> before
//=> A: hello
//=> after

引数も渡せる。

var B = function() {}
B.prototype.hello = function(user) {
  console.log('B: hello', user)
}

injectHello(B)
b.hello('山田')
//=> before
//=> B: hello 山田
//=> after

結局のところ、名前ベースであるところが一番ネックだなと思った。
この記事含めて2時間ぐらいしか調査してないので、何か間違いがあったらコメントまでお願いします。

14
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?