読者です 読者をやめる 読者になる 読者になる

ravelll の日記

よしなに

Mackerel で金の買取相場を監視する

tech

去年末、社員旅行での抽選会で純金が当たった。

まだしばらく売る気はないのだけど、ひとまず金相場が見たい、ということで Mackerel で監視することにした。

稼働環境は Amazon EC2Amazon Linux)です。

手順

まずは mackerel-agent をインストール。APIKEY は各自のものに読み換えてください。

$ curl -fsSL https://mackerel.io/file/script/amznlinux/setup-all-yum.sh | MACKEREL_APIKEY='yourmackerelapikey' sh

次に監視するパラメータを取得・設定するスクリプトを設置。

#!/bin/bash

name="GoldPrice"
monitor_time=`date +%s`
market_rate=`curl http://gold.mmc.co.jp/market/gold-price/ | grep -A1 metalType1 | tail -1 | tr -d "\t" | tr -d "," | cut -b 4-7`
echo -e "${name}\t${market_rate}\t${monitor_time}"

設置したスクリプトを使いメトリックを作成するよう mackerel-agent.conf を修正。

$ sudo vim /etc/mackerel-agent/mackerel-agent.conf

[plugin.metrics.process]
command="bash /path/to/script.sh"
type="metric"

これでカスタムメトリックとして金相場のグラフが表示されます。

ラベルはグラフ右上の設定ページで変更できます。今回はストレートに「金相場」としました。

f:id:ravelll:20170214221215p:plain

よさそうです。

グラフが表示されないときは /var/log/mackerel-agent.log を見ると原因が特定できると思います。

今後

金相場の情報を取得しているページの更新が日に1回のようだし、不必要に高頻度なスクレイピングは行儀が悪いのでエージェントのフェッチ間隔を広げたい。

今は1分毎にメトリックに Post されており、ひたすら平坦なグラフが続いていて情報価値が低い。相場が上下する経過が見たいのだ。

plugin.metrics.* の実行間隔は設定できるのかなと mackerel-agent のコードを読んだのだけど、config/config.go#L214 の変数を toml からの入力で変更する箇所は無いように見えるのでできない…?

plugin.checks.* での check_interval や execution_interval のようなパラメータがあるのかなと思ったのだけど無いのかな。会社の有識者の方々に聞いてみよう。

追記

はてな社のセールスエンジニアである id:a-know さんより、サービスメトリックにするとよいとのアドバイスをいただきました。ありがとうございます!!

オブジェクト指向設計実践ガイド 第6章

book ruby tech

6章は継承の話。既知の内容も多かったけど、フックメソッドのテクニックは知っておらず、なるほど〜という感じだった。

徐々にサンプルコードのコンテキストが厚くなってきたので写経しつつ読み進めた。

transcriptional_codes/guide_for_object_orient_designing/chapter6 at master · ravelll/transcriptional_codes · GitHub

それにしてもこの本、読み進めているとたびたび唐突に自転車が猛烈プッシュされてきて、著者の抑えきれない自転車愛が伝わってくるのが面白い(知識があるだけなのかもしれないけれど)。まさかリカンベントまで出てくるとは。

6章のホット・バイシクル・センテンシーズはこちらです。

「ハンドルバーのテープはそこまで重要でなさそうですが、
実際には(タイヤやチェーンと)同じくらいに必要とされます。
誇りを持つサイクリストの中に、横れたり破けたりしたバーテープを許す人はいません」

第6章 継承によって振る舞いを獲得する

6.1 クラスによる継承を理解する

  • 継承:メッセージの自動委譲の仕組み
    • あるオブジェクトが受け取ったメッセージに応答できないとき他のオブジェクトにそのメッセージを委譲する

6.2 継承を使うべき箇所を識別する

  • オブジェクトの属性による分岐
    • ダックタイピングが解決する問題と同じパターン
    • 「自身の分類を保持する属性を確認し、自身に送るメッセージを決定する」
  • type, category という変数名はその根底にあるパターンへの気づきを促している
  • 継承は共通の振る舞いを持つもののいくつかの面においては異なるという強く関連した型の問題を解決する
  • サブクラスはスーパークラスの全てであり、スーパークラスを上回るものである

6.3 継承を不適切に適用する

6.4 抽象を見つける

  • 継承が効果を発揮するために必要な2つのルール
    1. モデル化しているオブジェクトが “一般 - 特殊” の関係を持っていること
    2. 正しいコーディングテクニックを使っていること
  • Ruby は他者を信頼する性質から Java における abstract 等ののキーワードを持たず、制約を加えることもない
  • 抽象クラスはサブクラスが作られるためだけに存在する
    • 抽象クラスがサブクラス間で共有される振る舞いの格納場所を提供する
    • サブクラスがそれぞれに特化した振る舞いを用意する
  • サブクラスを1つだけもつ抽象クラスを作ることはほぼまったく意味がない
  • 階層構造を進める決断は、正しい設計のための情報が未だ無いかもしれない、というリスクを受け入れること
    • 今2種類のカテゴリは3種類になる見込みがあるなら階層構造を作ったほうがいいかもしれない
    • 2種類から増えないならば階層構造を作らないほうが低コストかもしれない
    • 可能なら判断を待つ。しかし最善だと思えるならば進む
  • 既存のコードはスーパークラスに昇格させるよりサブクラスに降格させる方が簡単
    • 抽象クラスを作るときは一度全体を降格させてから必要な分の実装を昇格させるのがよい
  • リファクタリングやその他の戦略を決める際は「もし間違っているなら何が起こるか」を質問するのが有用
  • 信頼できない階層構造は、それと関わるオブジェクトに階層構造の癖を知るよう強要する
    • そのときよく使われる手段が、オブジェクトのクラスの明示的な確認
  • 設計者の決断に常に伴う2つのコスト
    1. 実装コスト
    2. 実装が間違いと分かったときの変更コスト
  • Bicycle クラスは初期値をメソッドで包み、それをオーバーライドすることで何かに特化できる機会をサブクラスに与えている
    • スーパークラス無いで基本構造を定義し、サブクラス固有の情報を得るためにメッセージを送る
    • このようなテクニックをテンプレートメソッドパターンという
  • テンプレートメソッドをサブクラスで特化させる必要があると明示的に示すには、スーパークラスのメソッドで未実装と分かるようなエラーを出す

6.5 スーパークラスとサブクラス間の結合度を管理する

  • サブクラスは自身を特化する振る舞いについて知っているのは良いが、super で抽象スーパークラスとの関わり方まで知るよう強制するのは良くない
    • 全てのサブクラスが正確に同じ箇所で super する必要があるのは、新たにサブクラスを書くときにエラーを作る可能性を高める
    • サブクラスが super を送ることは、サブクラスはスーパークラスの処理を知っていて、その知識に依存しているということ
  • super を送ることをサブクラスに求めるのではなく、フックメッセージを用意してスーパークラスから情報を取得する
    • サブクラスは自身について「何を」特化する必要があるかについては責任を負うが、「いつ」特化するかについては責任がなくなる

まとめ

  • 継承は共通の振る舞いを持ちつつも、いくつか相違点のある型に関する問題を解決する
  • 抽象的なスーパークラスを作る最も良い方法は具象的なサブクラスからコードを押し上げること
  • 正しい抽象の設計が最も簡単なのは存在する具象クラスが少なくとも3つあるとき
  • サブクラスはフックメソッドによってスーパークラスアルゴリズムを知らなくとも特化できるようになる

オブジェクト指向設計実践ガイド 第5章

5章はダックタイピングの話。Ruby の特徴としてよく語られますね。

勘所がつかめると設計が洗練されるだけでなく OSS プロダクトのコードリーディングが捗って良さそうだな〜と思いました。

動的/静的型付け言語の話はなかなか強い口調で語られていて、読んでいて少しヒヤヒヤするところがあった。

5章 ダックタイピングでコストを削減する

  • ダックタイプ:どの特定のクラスにも結びつかない(クラスをまたぐ)パブリックインターフェース
  • 「アヒルのように鳴き、アヒルのように歩くならば、それはアヒルである」

5.1 ダックタイピングを理解する

  • Ruby ではパブリックインターフェースを信頼を元にオブジェクトの振る舞いを期待する
    • 「あるオブジェクトの型を知っている」ことは「オブジェクトが応答できるメッセージを知っている」ということ
    • あるクラス A のオブジェクトと相互作用するオブジェクトに必要なことは「相手が A のインターフェースを実装していると信頼する」こと
  • オブジェクトの使い手はそのクラスを気にする必要がなく、気にするべきでない
    • 重要なことはオブジェクトが「何であるか」でなく「何をするか」
  • ダックタイプのパブリックインターフェースは契約を表す
  • Trip#prepare は Mechanic クラスには依存していないが「prepare_bicycles に応答できるオブジェクトを受け取る」ことに依存している
  • ダックタイプ化は少しの理解力と引き換えに拡張の容易さを提供する
    • 具象的なコードは理解易・拡張難、抽象的なコードは理解難・拡張易
  • オブジェクト指向におけるポリモーフィズム:種々のオブジェクトが同じメッセージに応答できる能力

5.2 ダックを信頼するコードを書く

  • クラスによって分岐する case 文は未特定のダックの存在を示唆する
    • 共同作業するオブジェクトについての知識を持ちすぎていて、信頼が欠けている
  • ダックタイプを実装するクラスは振る舞いもいくらか共有する必要がある
    • モジュールによってロールを共有する方法に続く
  • ダックタイプは時と場合を考えて使う
    • ダックタイプを見つけて実装してもアプリケーション全体のコストが下がらない場合もある

5.3 ダックタイピングへの恐れを克服する

  • コンパイラは不慮の型エラーからプログラマーを救うことはできない
    • 変数を新しい型にキャストできる全ての言語には脆さがある
  • 静的型付けによって安全になるという考えは幻想である
  • 現実の世界で、コンパイラで防げる実行時の型エラーはほぼ確実に起こらない
    • コンパイラの助けがなければ型エラーは起こる、という説に対して
  • 動的型付け言語は、高コスト低価値なコンパイル時の型検査と、コンパイル/make サイクルを除くことで得られる莫大な効率性とを交換してくれる
    • :fire:

5.4 まとめ

  • ダックタイピングはパブリックインターフェースを特定のクラスから切り離し、「何であるか」ではなく「何をするか」によって定義される仮想の型を作る

第110回 PHP 勉強会に行ってきた + LT してきた

PHP event presentation tech

phpstudy.doorkeeper.jp

久しぶりの PHP 勉強会。最後に行ったのは第96回で、調べてみたらもう1年以上も前のことだった。当時に比べれば随分と PHP に詳しくなったと思う。

LT は最近踏んだバグについて話してきた。そこそこ盛り上がって安心しました。

speakerdeck.com

勉強会全体としては、 @ex_takezawa さんの DDD の話で過去に自分がチームに DDD 導入しようとして爆死した思い出が蘇ったり、@kuwahara_jsng さんから自分に知見があまりない CodeIgniter4 の話が聞けたり、飛び入り参加で @tomzoh さんがめっちゃいい話されてたりで、短時間ながらとても楽しく得られる物があった会でした。

来月も何かいいネタがあれば LT 応募しようと思います、お疲れ様でした!

オブジェクト指向設計実践ガイド 第4章

tech book ruby

パブリックインターフェースについての話。デメテルの法則についても触れていました。

第4章 柔軟なインターフェースを作る

  • オブジェクト指向アプリケーションは「クラスから成り立ち」「メッセージによって定義される」
  • オブジェクトの責任 = オブジェクトが何を知っているか
  • オブジェクトの依存関係 = オブジェクトが誰を知っているか

4.1 インターフェースを理解する

  • オブジェクト同士が複雑に依存してしまうような設計の問題は、クラスが何を「する」かでなく、何を「明らかにする」か、の視点が欠けていることにある
  • 他のオブジェクトからの利用が意図されているメソッドが、そのクラスのパブリックインターフェースを構築する

4.2 インターフェースを定義する

  • レストランの厨房から見て、お客さんが使うことが期待されるパブリックインターフェースはメニュー
    • メニューを使うことで厨房が「どのように」料理を作るかを関知させず「何を」望むかをお客さんに頼ませることができる
  • パブリックインターフェースの特性
    • クラスの主要な責任を明らかにする
    • 外部から実行されることが想定される
    • 気まぐれに変更されない
    • 他者がそこに依存しても安全
    • テストで完全に文書化されている
  • パブリックインターフェースはクラスの責任を明確に述べる契約書
  • 「変更の可能性が低いところにのみ依存する」という考えはクラス内のメソッドにも当てはまる

4.3 パブリックインターフェースを見つける

  • ドメインオブジェクト = アプリケーションにおいてデータと振る舞いの両方を兼ね備える名詞を表すもの
  • 設計時にはドメインオブジェクトに集中はせず、オブジェクト間のメッセージに注意を向ける
  • オブジェクトとメッセージを実験するにはシーケンス図を使うと良い
    • パブリックインターフェースをあらわにし、実験し、定義するための手段となる
    • メッセージに集中することを助け、テストで最初に明らかにしたいことへの合理的な見当をつけられるようになる
  • メッセージに基づく視点はクラスに基づく視点よりも柔軟なアプリケーションを生む
  • オブジェクトが存在するからメッセージを送るのではなく、メッセージを送るためにオブジェクトは存在する
  • パブリックインターフェースが小さい = 他から依存されるメソッドがわずかしか無い

4.4 一番良い面(インターフェース)を表に出すコードを書く

  • インターフェースこそが全てのテストや他のどんなコードよりもアプリケーションを定義し将来を決定づける
  • プライベートメソッドは全くテストしない、もしくはパブリックなメソッドからは隔離する
    • 不安定なプライベートメソッドに依存するテストを書かない
  • 外部フレームワークへの依存は技術的負債の一形態である
  • パブリックインターフェースを構築するときは、他者に要求するコンテキストが最小限になることを目指す
    • メッセージの送り手が、クラスがどのように振る舞いを実装しているかを知ることなく、望むものを得られるようにする

4.5 デメテルの法則

  • デメテルは3つ目のオブジェクトにメッセージを送る際、異なる型の2つ目のオブジェクトを介すことを禁じる
    • 「直接の隣人にのみ話しかける」
  • 中間オブジェクトを介して遠くの属性を取得することが最も低コストな場合もある
    • 変更のコスト・頻度と、違反修正のコストを比べてバランスをとる
    • デメテルの法則を違反することで負うリスクは安定した属性に対しては低い
  • メッセージチェーンを除去する方法の1つは、メッセージを移譲すること
    • 結合を隠しただけで実際にはコードの結合が解かれていないような場合もある。移譲は注意して行うこと
  • メッセージに基づく視点でメッセージを見つけたなら、そのメッセージは何らかのオブジェクトのパブリックインターフェースとなる
    • そのオブジェクトが何のオブジェクトかはメッセージ自体が導いてくれる

4.6 まとめ

  • オブジェクト指向アプリケーションは、オブジェクト間で交わされるメッセージによって定義される
    • メッセージの交換はパブリックインターフェースに沿って行われる
  • メッセージが「受け手がどのように振る舞うか」を伝えるのではなく、相手を「信頼」し送り手が望むことを頼むものであるとき、柔軟なパブリックインターフェースを自然に進化させていく

オブジェクト指向設計実践ガイド 第3章

book ruby tech

読み進めるうちにしばしば「あのプロダクトのあの実装はこういう意図だったのでは!」と気づいて、その瞬間が気持ち良い。

第3章では特に「他クラスへのあるメッセージ送信についての依存を、そのメッセージに応答できるダックタイプへの依存に変えるとき、それはインタフェースを定義している」という趣旨の文に唸らされた。

3章 依存関係を管理する

  • オブジェクトが現実世界の問題の特徴を反映し、オブジェクト間の相互作用が解決策を用意する

3.1 依存関係を理解する

  • テストはコードを参照するがゆえに、コードに依存する
    • テストに慣れないうちはコードと過度に依存したテストを書きがち

3.2 疎結合なコードを書く

  • 依存オブジェクトの注入によるコード整形は、クラス名やそのクラスに送るメソッド名を知っておく責任が他のクラスにあるのでは、と疑える能力に左右される
  • コントロールできない外部のクラス名に対する依存をどのように管理するかはアプリケーションに多大な影響を及ぼす
  • 複雑なメソッドはそうでないメソッドよりも変更が必要になる可能性が高い
  • 引数が必要なメッセージを送るとき、送り手は引数についての知識を持たざるをえない
  • 真偽値を引数にとったり引数の false と nil を区別したいときは || でなく fetch を使うのが良い
  • 自身のアプリケーション内のクラスは自身のアプリケーションが所有するコードのみに依存するべき
  • 他クラスのインスタンス作成のみを目的とするクラスをオブジェクト指向設計ではファクトリーと呼ぶ

3.3 依存方向の管理

  • 各クラスの依存は自分より変更されないクラスへの依存となるように管理する
  • 依存する他クラスへのメッセージに応答できるダックタイプを定義する ≒ インタフェースの定義
  • 抽象化されたものへの依存は具象的なものへの依存よりも常に安全

3.4 まとめ

  • 依存関係の管理において鍵となるのはその方向を制御すること

"オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方" を読み始めた

tech book ruby

2度目のパーフェクト PHP の読了を果たした一昨日から、オブジェクト指向設計実践ガイドを読み始めた。

RubyKaigi の頃あたりに 訳しました:「オブジェクト指向設計実践ガイド」 - Misoca開発ブログ のエントリを読んで気になりつつ終ぞ今日まで読むには至っていなかったのだけど、同僚の @kymmt90 が読んでいていい感じとのことだったので読み始めた。まだ2章までしか読めてないけれど、既に面白い。

もうしばらくすると仕事でガッツリ Ruby を書くことになりそうなので、そのためのリハビリも兼ねている。

今年はオブジェクト指向設計デザインパターンといった、将来つらくならない開発するための体系的な知識を付けたい気持ちがある。

理解を深めるためにも、メモを付けつつ読んでいこうと思う。

第1章 オブジェクト指向設計

1.1 設計の賞賛

  • オブジェクト指向とは依存関係を管理すること
  • 知識を持ちすぎたオブジェクトは制約が増えテスタビリティが下がるだけでなく、複製もされやすくなる
  • 実用的な設計は未来を予測・選択するのではなく、あとにでも設計ができるよう変更コストを下げる

1.2 設計の道具

  • 設計における道具は「原則」と「パターン」

1.3 設計の行為

  • 設計の行為と実装の行為が乖離した時オブジェクト指向ソフトウェアは失敗する
  • 設計はインクリメンタルに行われるべきで、アジャイル開発がはまる

1.4 オブジェクト指向プログラミングのかんたんな導入

1.5 まとめ

  • 実践は常に理論より物事を知っている
  • 実践とは配られたカードの中でベストを尽くすことの積み重ね

第2章 単一責任のクラスを設計する

2.1 クラスに属するものを決める

  • 設計はアプリケーションの可変性を保つために技巧を凝らすことであり完璧を目指す行為ではない
  • 変更しやすいコード ... "TRUE" なコード
    • Transparent: 見通しが良い
    • Reasonable: 合理的
    • Usable: 利用性が高い
    • Examplary: 模範的

2.2 単一の責任を持つクラスをつくる

  • 短絡的な再利用はクラスの目的を曖昧にし責任を増やす
  • 単一責任の原則は「クラスがすることは全てそのクラスの目的に強く関連すること」を求める
  • 何もしないことによる将来的なコストが今と変わらなければ設計の決定を延期する
    • 決定は必要なときにのみ、その時点で持っている情報を使って行う

2.3 変更を歓迎するコードを書く

  • インスタンス変数は大抵の場合アクセサメソッド等によってオブジェクトとして扱えるようにするのがよい
  • メソッドもクラス同様に単一の責任をもつべき
  • メソッドを単一責任にするためのリファクタリングは最終的な設計が見えない状況でもするべき
    • 隠蔽されていたクラスの目的が明らかになる
    • メソッドにコメントする必要がなくなる
    • アプリケーションにとって健康的なコードの書き方(再利用)を促進する
    • メソッドの移植性が高まる

2.4 ついに、実際のWheelの完成

2.5 まとめ