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

#18 「サービスの負債を減らしましょう」tech.kayac.com Advent Calendar 2012

こんにちは、入社4年目にして初投稿する、あきひと(@takihito)です。

このエントリーは tech.kayac.com Advent Calendar 2012 の18日目の記事になります。

今年の12月で5周年を迎えた某サービスの運用開発をしています。自分が関わり始めてからは4年ほどです。 その間にサービスの成長に伴い溜まった負債を減らす方法をいくつか紹介したいと思います。 (テーマは「2012年のマイイノベーション」ですが特に気にせず書かせて頂きます)

カプセル化

リリース時にコントローラにベタ書きしてしまったコード、開発速度や納期を優先するとよくあります。 このままでは単体テストも書きにくく、品質や機能拡張の障害にもなります。こんな時にはカプセル化をしましょう。

advent_calendar_2012_18_fig1.png

ベタ書きしたビジネスロジックを上図のようなModelクラスを新たにつくって、移し閉じ込めてしまいまいます。 これでコードの見通しも良くなり、単体テストもしやすくなりました。 別のアプリケーション(スマホ/ガラケー)からも重複している処理を呼び出せるようになります。負債の一本化ですね。

並行稼動

長期運用をしていくと当初用意したしたサーバーリソースでは足りなくなってくることがあります。

たとえばWebアプリケーションがJobQueue経由でWrokerに画像ファイル等を保存させるような場合

  • 保存先のストレージが容量不足になりそう
  • 潤沢な 新ストレージに移行させたい
  • サービスは止めたくない

といったことが起きてきます。 そのような時には新ストレージに保存するNew Workerを用意し並行稼動させます。

advent_calendar_2012_18_fig2.png

並行稼動している間に旧ストレージから新ストレージにデータを移していきましょう。 データの移行が完了したら、プロキシサーバーからの参照先を新ストレージに切り替えます。 完全移行後も旧システムを暫く動かし、切り戻し出来るようにしておくと安心ですね。 ファイルベースの管理からS3やKVSなどに移行させる時などにも有効です。これで返済期限が伸びました。

疎結合

単体のアプリケーションに入れていた仕組みを外部に出すことで依存関係を整理し、保守性を高めることができます。

IPアドレスを利用してSPAM対策を行う例になります。

advent_calendar_2012_18_fig3.png

Webアプリケーションから外部のSPAM IP リスト(API)に直接アクセスしチェックを行うようにしていました。 チェックしたIPはKVSに一時保存し次回からはKVSを参照するような仕組みになっています。 ただ問題がないわけではなく

  • IP をチェックする箇所がサービス上に複数ある
  • SPAMerはIPや手法を頻繁に変えてくる
  • 外部のSPAM IP リスト(API)とは非同期に連携したい

といったことがあります。SPAM IP を管理する仕組みはWebアプリケーションから切り離したほうが良さそうです。

そこでシステム構成を以下のように変更しました。

advent_calendar_2012_18_fig4.png

外部のSPAM IP リストとの連携やSPAM IPを判定するロジックをWebアプリケーションから切り離し、新たにSPAM IP Serverを立てて移しています。 今後はSPAM IP Serverを保守していけば良いので、Webアプリケーションの肥大化を防ぐことにもつながります。他のサービスやアプリケーションとも連携を取りやすくなり、効率的にSPAM対策が行えるようになりそうです。

SPAM IP ServerはMemcached-Serverを使ってつくりました。 お手軽にmemcachedプロトコルのサーバーをつくることができ、WebアプリケーションからのIPチェックもgetでチェックするようにしています。面倒な仕事は外部に投げてスッキリ!

名前

コードの混乱により、上であげたような大鉈を振るうことができない場合には メソッド名やマジックナンバーを見直すだけでも十分効果があります。

sub dec24 {
    my $self = shift;
    return 'メリークリスマス';
}

dec24だと流石にわかりにくいので(自分にはわからないので)

sub merry_xmas {
    my $self = shift;
    $self->dec24()
}

としてmerry_xmasでも呼べるようにしましょう。 (人によってはtsuraiの方が分かりやすいかもしれません)

ハードコードしてしまったマジックナンバーも

 use constant {
     XMAS_EVE => 24,
     XMAS => 25,
 };
:
if ( $day == XMAS_EVE || $day == XMAS ) {
    return '定時で帰って酒飲むぞ!!';
}

としておくだけで分かりやすくなります。窓口がカワイイ子に代わるだけで、解決したりするものです。

まとめ

開発から運用フェーズとなると、モチベーションの維持が難しくなる時もあるかと思います。

先に伸ばしがちな仕事は、午前中の意思が枯渇していない時間にやったり(意思は消耗品) 新しい技術は管理画面や直接サービスと関係ない箇所に投入して様子をみるなどして 触れておくと良いかもしれませんね。

借金(負債)を減らして気持よく新年を迎えたいものです。

明日は、@shu223さんの記事です、お楽しみに!