Subscribed unsubscribe Subscribe Subscribe

Hatena Developer Blog

はてな開発者ブログ

薄いフレームワーク指向の Web クライアントサイドプログラミング

こんにちは、Web アプリケーションエンジニアの id:nanto_vi です。先日開催された Kyoto.js #12 において、「薄いフレームワーク指向の Web クライアントサイドプログラミング」と題した発表を行いました。とある Web アプリケーションの開発にあたって、JavaScript による GUI プログラミングにどう取り組んだかという話になります。当日のスライドの内容に口頭で伝えた内容を加え、以下にまとめます。


前提


Web アプリケーションを新規開発するにあたり、クライアントサイドをどう実現するか。ここでは開発期間が決まっているというのが大きな要因となり、チームメンバーの経験がある MVP アーキテクチャパターンを採用することにしました。

また、JavaScript を直接記述するのではなく、TypeScript を使います。

MVP アーキテクチャパターン

TypeScript で実現する MVP アーキテクチャパターン - Hatena Developer Blog

View は Presenter にユーザー入力を伝える、Presenter は View に表示更新させる、Presenter は Model を操作する、Presenter は Model の更新を通知される

  • MVVM (Model-View-ViewModel)
    • View と ViewModel が双方向データバインディング機構で暗黙的につながる
  • MVP (Model-View-Presenter)
    • View は Presenter へ明示的にユーザー入力を伝える
    • Presenter は View の表示を明示的に更新する

MVP アーキテクチャパターンは MVVM アーキテクチャパターンと似ています。しかしながら、MVP アーキテクチャパターンには (MVVM アーキテクチャパターンにおける双方向データバインディング機構のような) ブラックボックスとなる部分がないので、既存のフレームワークを用いなくても簡単に実装できます。

ライブラリの使用

  • View
    • jQuery (DOM 操作、イベントハンドリング)
  • Presenter / Model
    • jQuery (HTTP 接続、Promise)

既存のフレームワークを用いないといっても、既存のライブラリも使わないということではありません。ともすれば冗長になりがちな処理を簡潔化するため、jQuery を使っています。とはいっても、jQuery の機能を野放図に使うのではなく、レイヤーごとに特定の機能だけ使うようにしています。

コンポーネントの例

interface IMyView {
    update(): void;
}
interface IMyArgs {
    foo: string;
}

class MyPresenter {
    view: IMyView;
    foo: string;

    constructor(view: IMyView, args: IMyArgs) {
        this.view = view;
        this.foo = args.foo;
    }

    changeFoo(foo: string): void {
        this.foo = foo;
        // (4) Presenter が View に状態変更を知らせる
        this.view.update();
    }
}

class MyView implements IMyView {
    presenter: MyPresenter;
    $element: JQuery;

    // (1) ルーターから View のインスタンスを生成する
    constructor($element: JQuery) {
        this.$element = $element;
        // (2) View から Presenter のインスタンスを生成する
        this.presenter = new MyPresenter(this, {
            foo: this.$element.attr('data-foo'),
        });
        this.$element.on('click', this.onClick.bind(this));
    }

    onClick(event: JQueryEventObject): void {
        // (3) View が Presenter の状態を変更する
        this.presenter.changeFoo(Date());
    }

    update(): void {
        // (5) View が Presenter の状態を表示に反映させる
        this.$element.text(this.presenter.foo);
    }
}

View のインスタンスと Presenter のインスタンスは一対一対応しています。コンポーネントの表示に必要な「状態」は Presenter が持っていますが、それを実際の表示 (HTML 要素) に反映させるのは View の役目です。

View は Presenter の実装を知っていますが、Presenter は View のインターフェイスしか知りません。こうすることで、Presenter をテストする際に View のモックを使うことができ、DOM に触らずプレゼンテーションロジックをテストできます。

コンポーネント間の連携

  • 当初は、HTML 要素のカスタムイベントを通じて View 同士が連携
    • 親子関係にないコンポーネントの連携が大変
      • 共通の親に仲介コンポーネントを設けるなど

当初はコンポーネント間の連携を実現するのに、jQuery のイベント機能を使って View 同士をつなげていました。しかし、それだと親子関係にない HTML 要素それぞれに対するコンポーネント同士を連携させるため、共通の祖先要素に対して仲介役のコンポーネントを設置するといった必要が出てきます。そのままだと連携するコンポーネントの数が増えたときに複雑さが増加しそうなので、後述する Model レイヤーでの連携を試みました。

Model を通じたコンポーネント間の連携

  • 複数の Presenter が Model の同一インスタンスを参照する
    • Multiton パターン (Singleton パターンの拡張)
class MyModel {
    private static instances: { [myId: string]: MyModel };
    static getInstance(myId: string): MyModel {
        let instance = MyModel.instances[myId];
        if (!instance) {
            instance = MyModel.instances[myId] = new MyModel(myId);
        }
        return instance;
    }

    constructor(myId: string) {
        ...
    }
}
  • Model の状態変化を複数の Presenter に通知する
class MyPresenter {
    constructor(...) {
        ...
        this.myModel = MyModel.getInstance(myId);
        this.myModel.on('foo', () => { this.view.update(); });
    }
}
class MyModel {
    on = Emittable.on;
    off = Emittable.off;
    emit = Emittable.emit;

    doSomething(): void {
        ...
        this.emit('foo');
    }
}

Presenter 同士が Model を介して 連携するためには、複数の Presenter のインスタンスが同一の Model のインスタンスを参照する必要があります。きちんとやるならレジストリだ依存性注入だといった話になるのでしょうが、簡単化のため Multiton パターンを使って Model のインスタンスを生成することにしました。

Presenter 同士が Model を介して連携するためには、ある Model のインスタンスの変化を複数の Presenter のインスタンスへ伝える必要があります。ここでは、Observer パターンを使って Model の変化を Presenter へ伝えることにしました。

例: 「いいね!」できるユーザー

class LikePerformer {
    static getInstance(...) { ... }

    userId: string;
    targetId: string;
    isLiking: boolean;

    constructor(userId: string, targetId: string, isLiking: boolean) {
        this.userId = userId;
        this.targetId = targetId;
        this.isLiking = isLiking;
    }

    toggleLike(): JQueryPromise<void> {
        let isLiking = this.isLiking;
        let apiURL = `/users/{ this.userId }/targets/{ this.targetId }/{ isLiking ? 'unlike' : 'like' }`;
        return $.post(apiURL).then(() => {
            this.isLiking = !isLiking
            this.emit('status-change');
        });
    }
}

例として、Facebook の「いいね!」のような機能を実現するための Model を考えてみます。「『いいね!』できるユーザー」を表すクラス LikePerformer は、対象を今現在「いいね!」しているかどうかの状態 isLiking を持っています。isLiking の値が変わるたび status-change イベントを発行し、Presenter に向けて状態の変化を伝えます。

toggleLike メソッドが Promise を返しているのは、アプリケーションを利用するユーザーへのエラー通知のためです。エラーもイベントとして複数の Presenter に通知してしまうと、各コンポーネントがそれぞれエラー通知を出し、その内容が重複してしまうかもしれません。そこで、ユーザーへのエラー通知は toggleLike メソッドを呼び出した Presenter のインスタンスが責任を持つこととします。

例: コメントを促すメッセージ

「いいね!」したがコメントしていないユーザーに対して、「『いいね!』の次はコメントしましょう」というメッセージを表示したい。

class CommentSupportMessagePresenter {
    constructor(...) {
        this.likePerformer = LikePerformer.getInstance(...);
        this.commentAuthor = CommentAuthor.getInstance(...);

        this.likePerformer.on('status-change', () => { this.view.update(); });
        this.commentAuthor.on('status-change', () => { this.view.update(); });
    }

    get isShown(): boolean {
        return this.likePerformer.isLiking && !this.commentAuthor.hasComment;
    }
}

class CommentSupportMessageView {
    update(): void {
        this.$element.toggle(this.presenter.isShown);
    }
}

前述の Model を利用する Presenter の例です。ユーザーが「いいね!」しているかどうかを知りたい Presenter は、LikePerformer のインスタンスを参照し、その状態が変化したときに自らの状態変化も View に伝えます。結果として、別のコンポーネントが引き起こした「いいね!」状態の変更により、このコンポーネントの表示が変化します。

テスト

  • テスト時にできるだけ DOM に触りたくない
    • DOM は状態の塊であり、テストのために用意するのも大変
  • Presenter のテスト時には View のモックを使う
    • DOM を用意せずにプレゼンテーションロジックをテストできる
  • 一から始めるJavaScriptユニットテスト - Hatena Developer Blog
    • Presenter / Model のテストはメソッドごとに
    • View のテストは JSDOM を使い、「ボタンがクリックされたら要素が表示される」といったシナリオに沿って

上で述べたように、Presenter をテストする際には View のモックを用意します。また、Sinon.JS を使って setTimeoutXMLHttpRequest といったブラウザの機能をモックしています。

View と Presenter の分担

  • View に条件分岐が出てきたら黄信号
// ○ OK
class MyView {
    updateVisibility(): void {
        if (this.presenter.isShown) {
            this.element.classList.remove('isHidden');
        } else {
            this.element.classList.add('isHidden');
        }
    }
}
// × NG
class MyView {
    updateVisibility(): void {
        if (this.presenter.currentScore < this.presenter.maxScore) {
            this.element.classList.remove('isHidden');
        } else {
            this.element.classList.add('isHidden');
        }
    }
}
  • イベントのデフォルトアクションをキャンセルする
class MyFormPresenter {
    handleSubmit(): boolean {
        if (!this.shouldHandle) return false;

        this.doSomething();
        return true;
    }
}

class MyFormView {
    onSubmit(event: JQueryEventObject): void {
        let isHandled = this.presenter.handleSubmit();
        if (isHandled) {
            event.preventDefault();
        }
    }
}
  • Presenter → View → Presenter と呼び出してはいけない
// × NG
class MyPresenter {
    doSomething(): void {
        this.updateVisibility();
    }

    hide(): void {
        ...
    }
}

class MyView {
    updateVisibility(): void {
        ...
        // View をモックに置換すると hide メソッドが呼び出されなくなる
        this.presenter.hide();
    }
}
  • 「状態」と「状態遷移のトリガー」は Presenter が持つ
    • View は「状態遷移のトリガー」を呼び出し、「状態」を DOM に写すだけ

MVP アーキテクチャパターンの悩みどころのひとつが、View と Presenter をどう分割するかです。「DOM に触らずプレゼンテーションロジックをテストする」という大前提があるため、個別のコンポーネントに関することは基本的に Presenter に記述し、どうしても DOM (HTML 要素) を扱わざるを得ない部分だけ View に切り出すようにします。

DOM イベントを扱うときも、イベントオブジェクトを直接 View から Presenter に渡すのではなく、DOM に依存しない数値・文字列を取り出してそれを Presenter に渡すようにします。イベントのデフォルトアクションのキャンセルも、するかどうかの判断は Presenter で、実際にキャンセルする (イベントオブジェクトの preventDefault メソッドを呼び出す) のは View でとなります。

複雑になる処理

  • Presenter が View に対して Data Transfer Object を公開する
    • ある View に特化した DTO を用意することで、View を薄くできる
  • リストの項目の追加・削除・並べ替え
    • VirtualDOM が本領を発揮する分野
  • 手続き的か宣言的か
    • UI は宣言的に書けたほうが楽
// 手続き的 (素の DOM API)
let link = document.createElement('a');
link.href = url;
link.textContent = label;
element.appendChild(link);
// 手続き的 (jQuery)
let $link = $('<a>').attr('href', url).text(label);
$element.append($link);
// 宣言的 (JSX)
<a href={url}>{label}</a>
[%- # 宣言的 (Perl の Text::Xslate::Syntax::TTerse) %]
<a href="[% url %]">[% label %]</a>

View はできるだけ薄く保つべきですが、複雑な処理が入ってしまうこともあります。代表的な例がリストの項目の追加・削除・並べ替えでしょう。この部分をうまいことを隠蔽してくれる仮想 DOM ライブラリ (React など) がうらやましくなります。

View での DOM 操作はどうしても手続き的になりがちです。コンポーネントによってはサーバー側で生成した HTML 片を挿入することで宣言的な性質を取り入れているところもありますが、仮想 DOM ライブラリを使って最初から宣言的に記述するほうがわかりやすいことも多いでしょう。

質疑応答

  • 結局開発期間に間に合ったのか?
    • 間に合ったが、今後も同様の方針を継続するには文書整備の必要があり、保守性に不安が残る
  • 別のアーキテクチャパターンを混ぜられるか?
    • 基本的にコンポーネント単位で実装しているので、あるコンポーネントだけ Flux アーキテクチャパターンで実装するといったことも可能
  • MVP パターンで検索すると Web の事例が出てこない。どう教育していくのか?
    • この資料を含め、自分たちで文書を整備するしかない

今後もこの方針を続けていけるかどうかというのは難しい点です。慣れていればまずコンポーネントの状態と状態遷移を洗い出して Presenter から書き始められるのですが、Web クライアントサイドプログラミングに慣れていないと View から書き出し、都度 Web ブラウザで確認することになります。そうなると View にプレゼンテーションロジックが詰め込まれ、View が厚くなってしまいがちです。

Flux / Redux アーキテクチャパターンのほうが文書も豊富で学習しやすく、状態と状態遷移を意識づけることもしやすいかもしれません。


まとめ

以上で見てきたように、クライアントサイドプログラミングが小・中規模に収まるなら、大掛かりなフレームワークを使わずとも開発は可能です。しかし、それにはアプリケーションの状態の把握や DOM 操作の知識が必要であり、一概に学習コストが低いとは言い切れません。

はてなでは AngularJS や React + Redux を導入しているチームもあり、それぞれのメリット・デメリットを共有して今後に役立てていければと思っています。あなたもはてなで一緒に JavaScript (TypeScript) を書いてみませんか?

hatenacorp.jp

YAPC::Kansai 2017 OSAKA にはてなから4人のエンジニアが登壇します

こんにちは。はてなアプリケーションエンジニアの id:astj です。 Perl は5も6も好きです。
昨年12月の YAPC::Hokkaido を皮切りにリブートした YAPC::Japan の第2弾として、来る2017年3月4日に YAPC::Kansai 2017 OSAKA が開催されます。 Perlを軸としたITに関わる全ての人のためのカンファレンスであるこちらのカンファレンスに、はてなのエンジニアが4名(前夜祭を含めると5名!)登壇しますので以下にトークを紹介します!

既にチケットは売り切れてしまっていますが、参加されるみなさまと会場でお会いすることを楽しみにしています。
詳細はカンファレンス公式サイトをご覧下さい。

yapcjapan.org

また、カンファレンスの前日である3月3日にはYAPC::Kansai 2017 OSAKA 前夜祭 in大阪も開催されます。こちらも既にチケットは売り切れてしまっていますが、この前夜祭で開催される「突撃!隣の開発環境!」にも id:hitode909 id:Songmu id:papix の3名がはてなから参加します。前夜祭から参加される方はこちらもよろしくお願いします。

登壇内容

PerlのWebアプリケーションをデプロイする時に僕達が考えたこと

Webアプリケーションを作ったとき, それを実際にユーザーに届けるためには, そのWebアプリケーションを"デプロイ"して, ユーザーが利用可能な状態に設置しなければなりません.
最初は, 開発者自らがコマンドを入力する, 手動のデプロイで十分かもしれません. しかし, その作業を何度も繰り返す場合, アプリケーションの構成上少し手順が複雑な場合, あるいはデプロイを行うサーバーの台数が増えてくると, 手動でコマンドを入力するデプロイだと少し厳しくなってきます.

本トークでは, 主に趣味で開発するような小規模なPerl製Webアプリケーションのデプロイ戦略や, そのために有用な道具類の紹介をします.
具体的には, 以下のような内容が含まれる予定です.

  • デプロイとは?
  • 手動デプロイと自動デプロイ
  • デプロイの自動化ツールについて
  • Push型とPull型
  • Graceful Restart
  • バッチやワーカーのデプロイ
  • デプロイ対象をどのように管理するか?

「PerlでWebアプリケーションを作ってみたけど, どういう感じにデプロイすればいいんだろう?」とお悩みの方には, きっと興味深くお聴きいただけるのではないかと思います.

http://yapcjapan.org/2017kansai/talks.html#talk-29

また id:papix は 12:00-12:40 に C会場で行われる Perl入学式の座談会、"Perl入学式座談会 〜これまでの軌跡を振り返り, そして未来へ〜" にも登壇予定です!

Perl 6 で Web Application Framework をつくる

Web アプリケーションの開発をやっていると、誰もが一度は自分で Web Application Framework を作ってみたくなる物ではないでしょうか。実際の本番で導入するかは別にして、その言語におけるWebアプリケーション開発の仕組みを理解するためには重要な試みだと思っています。今回は、 Perl 6 でシンプルな Web Application Framework を作る話から、 Perl 6 での Web アプリケーション開発についてお話ししようと思います。

http://yapcjapan.org/2017kansai/talks.html#talk-15

はてなシステムの考古学

㈱はてなは今年で設立から16年目を迎えます。人力検索はてなに始まり、はてなブックマーク、はてなブログといったコンシューマ向けサービスから、サーバ管理・監視をおこなうMackerelや他社との協業サービスなど数多くのサービスを手広く展開しています。一部のサービスは昔のまま10年以上も愛されて今も元気に動いている一方、新しいサービスを開発するときには新たな設計を選ぶこともしています。
このトークでは、はてなにおけるウェブサービス開発の軌跡をPerlエンジニアの観点から辿り、生き残ったもの・捨てられたものからポスト現代のサービス開発を探ります。

http://yapcjapan.org/2017kansai/talks.html#talk-27

Webエンジニアに知ってほしいRDBアンチパターン

最初は良かれと思ってした設計が後々大きなボトルネックになることが度々あると思います。
そんなWebエンジニアが陥りやすい罠(アンチパターン)をご紹介し、未来の苦労を一つでも減らせる、そんなセッションをお送りします。
今回は

  • 忘れ去られたバックアップ
  • 使われない制約
  • ロックの功罪

に触れたいと思います。
どれも胸に刺さる内容ですのでご期待ください!!

http://yapcjapan.org/2017kansai/talks.html#talk-5

スポンサーもしています!

はてなは YAPC::Kansai のスポンサー企業でもあります。会場ではノベルティの配布も行いますのでぜひお楽しみに!

採用情報

はてなでは Perl に限らず Web サービス開発に興味のあるエンジニアを募集しています。

hatenacorp.jp

「バックログに入らないタスクを可視化する仕組み」という話を技術勉強会でしました

こんにちは。アプリケーションエンジニアの id:daiksy です。

はてなでは毎週木曜日に技術勉強会を開催しています。

参考: 寿司と勉強会とエンジニア - Hatena Developer Blog

先週、当番が回ってきたので、「バックログに入らないタスクを可視化する仕組み」というトークをしました。

speakerdeck.com

詳細はスライドを見ていただくとして、この発表で定義された「税」などの用語が、さっそく社内でのコミュニケーションでも使われだして、エンジニア同士で、ある概念について共通の認識を持つためにもこういった場は効果があるな、と実感しました。

はてなでは、アプリケーションを構築する技術だけではなく、プロジェクトマネジメントやチームビルディングの知見などもこうして技術勉強会で共有されています。

学生さん向け「はてな&Wantedly 合同説明会」1月25日(水)に東京で開催します!

はてなは1月25日(水)に、エンジニア志望の学生さん向けにWantedlyさんと合同で会社説明会を開催します。

今回は会社説明だけでなく、エンジニア社員が普段どういう風に働いているのか をより知っていただく機会にするため、飲食を交えながらエンジニア社員と密に話ができる場を設けます。 当日ははてなとWantedlyさんのエンジニア社員で6つのブースをつくり、参加者はそれぞれのブースに交代で回っていただきます。

普段はあまり接することのない社員とざっくばらんに話す機会を通して我々やWantedlyさんについて深く知ることが出来る機会となっています。2社に少しでも興味のあるエンジニア学生さんは是非お越しください!

イベント日程と会場

  • イベント名: はてな&Wantedly 合同説明会
  • 対象:エンジニア志望の学生さん(くわしい応募要件は申し込みページをご覧ください)
  • 日時: 1月25日(水) 19:00-21:00(18:45 受付開始 / 懇親会含む)
  • 参加費: 無料
  • 定員:30名(応募者多数の場合は抽選とさせていただきます)
  • 会場:ウォンテッドリー白金台オフィス
    • 所在地:東京都港区白金台5-12-7 MG白金台ビル4階

当日参加予定の社員紹介

はてな

  • 大坪 弘尚(id:motemen / @motemen)
    • 株式会社はてな 最高技術責任者。 2008年、アプリケーションエンジニアとして、はてなに新卒入社し、はてなの新サービス開発に数多く関わる。2016年に最高技術責任者に就任。現在ははてなのプラットフォームでアプリケーションエンジニアとして業務に携わりつつ、技術組織全般の統括を行っている。
    • https://www.wantedly.com/users/12432
  • 松木 雅幸(id:Songmu / @songmu)
    • 慶應義塾大学環境情報学部で中国語と機械翻訳の研究に注力。卒業後中国へ渡り、ITベンチャーの立ち上げに関わる。その後に帰国し、印刷系SIerでの業務、カヤックでソーシャルゲーム開発のリードエンジニアなどの経験を経て、2014年9月にはてなに入社。東京オフィスでチーフエンジニアを務めるとともに、Mackerelというサーバー監視SaaSのディレクターを担当している。最近はGo言語がお気に入りで「みんなのGo言語」という本を共著で執筆しました。
    • https://www.wantedly.com/users/11167
  • 和田 将義 (id:masawada / @masawada)
    • 株式会社はてな Webアプリケーションエンジニア。 電気通信大学情報理工学部在学中に、はてなサマーインターン2014に参加。後にアルバイトを経て2016年に新卒入社。現在は、はてなブログチームで新機能の提案および開発を行う。
    • https://www.wantedly.com/users/313960

Wantedly

  • 川崎 禎紀 (@kawasy)
    • Wantedly 取締役CTO。 2012年4月よりビジネスSNS「Wantedly」の開発・ 運営に参画。開発、マーケ、採用・育成など、プロ ダクトと組織づくりに幅広く携わる。
    • https://www.wantedly.com/users/10599
  • 坂部 広大 (@koudaiii)
    • Wantedly インフラエンジニア。 Wantedlyインフラチームでサービス基盤の改善とツール開発に従事。「Docker を Production で使い続ける理由」(Wantedly Engineer Blog)、「Docker と Kubernetes を使って変化に強いインフラを作る」(Wantedly Engineer Blog)など、変化に強いインフラ作りに日々取り組んでいる。
    • https://www.wantedly.com/users/310906
  • 森脇 健斗 (@Kento_Moriwaki)
    • Wantedly 新卒二年目エンジニア。 大阪大学工学部を卒業後、Wantedlyに新卒入社。フィードチームとインターナショナルチームとして、施策を考えるところから開発まで、幅広く取り組んでいる。フロントエンドが好きで、WantedlyにReactを導入した。
    • https://www.wantedly.com/users/1468880

タイムスケジュール

時間 内容
18:45-19:00 開場
19:00-19:20 2社による会社説明
19:20-20:20 エンジニア交流会 (参加者同士でグループを設定させていただき、10分毎に6つのブースを回ります)
20:20-21:00 懇親会(軽食をご用意してあります)

※ 内容を変更する可能性があります

お申し込み方法

以下のページからお申し込みください。

wantedly.connpass.com

はてなサマーインターン2016のレポートサイトを公開しました

2016年8月15日から9月9日まで開催された、「はてなサマーインターン2016」のレポートサイトを公開しました。

はてなサマーインターンシップは、はてなでのサービス開発や研究を体験できる、学生向けのインターンシッププログラムです。カリキュラム前半の講義でWebサービス開発の基礎知識を身に付け、カリキュラム後半で開発チームの一員となってはてなが提供する各サービスの開発に取り組みます。これらの体験を通して、Webサービス開発者に必要となる知識と経験を得て、技術者として大きく成長してもらうことを目的としています。

レポートサイトでは、インターン生が過ごした20日間の様子や、はてなのサービスでどんな機能を開発したのかを紹介しています。今年は機械学習の講義や、特別講義のAWSハンズオンなど新しい試みも多く取り入れました。これらの詳細をぜひレポートサイトでご覧になっていただければと思います。次回以降のインターンに興味がある学生の皆さんも、ぜひご覧ください!

インターンシップ以外に、はてなではアルバイトも募集しています。はてなインターンシップに準じた教育プログラムで学んでいただいた後、はてなの各サービスに開発者として携わっていただきます。はてなで技術的に成長したい方の応募をお待ちしております!

2016年はてなWebオペレーションエンジニアのアウトプット

こんにちは、シニアエンジニアの id:y_uuki です。 はてなのWebオペレーションエンジニア8名が、この1年で対外的にアウトプットした成果物をまとめて紹介します。

座談会

今週、Webオペレーションエンジニアの座談会記事を公開しました。技術ブログや技術発表では表現しきれない一人一人の考え方や思いが垣間見えるコンテンツになっていると思います。

Software Engineering

Keepalivedのシンタックスチェッカ「gokc」を作った - ゆううきブログ

gokcというGoで作られたKeepalivedの設定ファイルのシンタックスチェッカーです。社内で普通に導入しています。

インフラエンジニアがGo言語でオペレーションツールを書くことについて - Hatena Developer Blog

Go 1.6 Release Partyでの発表内容です。Go言語が好き。

自作Linuxコンテナの時代 - ゆううきブログ Droot Internals // Speaker Deck

自分の用途にあったLinuxコンテナエンジンを自作しようみたいな話です。第9回コンテナ型仮想化の情報交換会@福岡での発表がベースになっています。

CPAN Authorになった (Pgtoolsリリースした) - tom__bo’s Blog

はてなインターン2015で作ってもらっていたPostgresの運用ツールの話です。アルバイトの id:tom__bo くんの成果です。

swiro - A switching route tool for AWS

EC2におけるRoute Tableベースのフェイルオーバツールです。アルバイトの id:taku_k くんに作ってもらいました。

サーバモニタリング向け時系列データベースの探究 / The study of time-series database for server monitoring // Speaker Deck

IOTS2016で招待講演で、Mackerelのための時系列データベースを求めてたどり着いた一つの結論の話です。

Varnishによる一貫性を考慮した積極的キャッシュ戦略実験 - でこてっくろぐ ねお

ISUCON6の予選を題材に、汎用的な手法でなるべく多くのアクセスをVarnishにキャッシュさせようとした試みです。

sabaviz Chefviz creates the dot files of recipes dependency-graph for graphviz.

これもアルバイトの id:tom__bo くんの趣味の成果です。はじめてみるサービスの依存関係の把握が難しかったので、依存関係を可視化するツールを作ってみたとのことです。

System Engineering

雑な LVS/TUN の解説図 - mura日記 (halfrack) LVSでTunnel方式のL3DSRを実現した様子の図解です。入社したときに、これがわかっていないとLVSオペレーションしてはいけないみたいなことを言われて勉強した記憶があります。

Linuxサーバにログインしたらいつもやっているオペレーション - ゆううきブログ よくあるLinuxコマンド集にみえますが、実際に入社してから使い続けたものを厳選しています。

ウェブアプリケーション開発に新言語を採用したときにインフラで考えたこと - ゆううきブログ ここ数年、はてなではアプリケーション開発言語としてScalaとGoが採用されているのですが、プログラムを書く以外の観点が見過ごされがちだったので課題についてまとめました。第3回関西IT系インフラ勉強会内容とだいたい同じです。

仮想化基盤Xenの性能評価 / Performance evaluation of virtualization platform Xen // Speaker Deck 第3回関西IT系インフラ勉強会での発表です。最近は1台に30近い仮想ホストが蠢くようになっているので、仮想化基盤の安定化が課題です。

nginxでproxy_hide_header, proxy_set_header, add_headerを書く時にはまりがちな罠 - でこてっくろぐ ねお nginxの設定は、上位のコンテキストから下位のコンテキストに設定を継承しようとするとハマりどころが増えるという話ですね。

最近AWSのENIの付け替え速度がチョッパヤになってる気がしたので測ってみた - でこてっくろぐ ねお id:dekokun という人はチョッパヤみたいな一昔前の俗語が好きなようです。これをデコ感と呼びます。

AWS EC2でのHTTP/2 or SPDY導入方法 - Hatena Developer Blog AWSでのHTTP/2 or SPDY運用の課題とPROXY protocol - Hatena Developer Blog

はてなでもHTTP/2の導入が進んでいます。ELBを使いつつ、HTTP/2を利用するのに癖があります。3部作といいつつ、3つ目はどうなったのでしょうか。(ALBがもうでてしまった)

PostgreSQLで異なるメジャーバージョン間のレプリケーション実験 - tom__bo’s Blog 第7回 PostgreSQLアンカンファレンス@東京に行ってきた - tom__bo’s Blog

PostgreSQLのオンラインバージョンアップ方法を調べてもらっていました。MySQLのように数珠つなぎレプリケーションをするわけにはいかないようです。自ら発表したいということで、第7回PostgreSQLアンカンファレンス@東京で発表してもらいました。

Googleが数千台もある10年前のLinuxディストリをライブアップグレードした話 - ゆううきブログ

CentOS5のEOLは来年3月で、ちょうどディストーションのアップグレードに興味がありました。Googleでさえ、かなり泥臭いことをやらないといけないことがわかりました。

はてなにおけるLinuxネットワークスタックパフォーマンス改善 / Linux network performance improvement at hatena // Speaker Deck

はてな・ペパボ技術大会の発表です。よくあるチューニングを除いて、ウェブサービスでLinuxネットワークスタックがボトルネックになるケースは多くはないのですが、ユーザをたくさん抱えているとカーネルレイヤのチューニングが必要になることがあります。

Mackerelにおける時系列データベースの性能改善 / Performance Improvement of TSDB in Mackerel // Speaker Deck

同じく技術大会の発表です。こちらは、時系列データベースGraphiteの性能改善事例です。パフォーマンスが低下したときに、カーネルレベルで分析し、PRをなげて問題解決しました。

計算量と僕とWeb開発 / computational complexity and I and Web // Speaker Deck

同じく技術大会でのゆるふわ?計算量の話です。競技プログラミングで鍛えた感覚でだいたい計算量がわかるとのことです。すごいですね。

負荷分散技術を選ぶときに考えること // Speaker Deck

同じく技術大会での発表です。ネットワークからミドルウェアのレイヤまで幅広く抑えられているのが特徴です。はてなではいろんなレイヤで負荷分散を実現しています。

仮想化基盤のリソース最適化 / Resource optimization on virtualization platform // Speaker Deck

同じく技術大会での発表です。仮想ホストを構築するときに、どこの物理サーバを選べば良いのかをがんばって探さないといけないという課題があり、数学的モデルに落とし込むことで最適な配置ができるというものです。現実には、かなり多くの制約条件があって、プログラマブルに値をとりにくいものもあるので、なかなか難しいですね。

はてなでの サービス信頼性向上のための 取り組み事例 // Speaker Deck

SRE tech talksでの発表です。 ちょうと社内でSRE輪読会をやっていたところ、声がかかったので良いタイミングでした。SREの視点を通して、最近のはてなのウェブオペレーションを俯瞰するとどうみえるかという内容になっています。

ISUCON予選突破を支えたオペレーション技術 - ゆううきブログ

Kyoto.なんか #2での発表内容です。ウェブオペレーションエンジニア視点で、ISUCONという競技を自分なりに捉え直したものです。

はてなのログ運用 これまでとこれから / Hatena Engineer Seminar #6 // Speaker Deck

Hatena Engineer Seminar #6 〜インフラ編〜の発表です。rsyslogからfluentdへの変遷など。参加された人に聞くと、リバースプロキシでcronでアクセスログ送信しているところ、意外とやっている人がいるということに驚きました。

はてなのサーバプロビジョニングについて / Hatena Engineer Seminar #6 // Speaker Deck

同じくセミナーでの発表です。Chefなどのconfigurationフェーズの話は世の中にたくさんでてますが、OSイメージの作成などbootstrapフェーズも含んだ話は意外と少ないのではでしょうか。

MySQL運用とらぶるすとーり〜^2 / MySQL-Troubleshooting-Story // Speaker Deck

同じくセミナーでの発表です。MySQL芸人こといちりんちゃんの磨きのかかった発表でした。テーブルの行数制限にあたった話とbinlog破損から救いを求めた話です。

はてなのサーバ/インフラを支える技術〜2016年新卒編〜 / OSC Tokyo 2016 Fall // Speaker Deck

OSC Tokyo 2016での新卒2人による発表です。新しい広告配信システムのインフラの話と、はてなのサーバ・ネットワークの基盤の紹介です。

セキュリティ会の取り組み - Hatena Developer Blog

セキュリティ会自体は、ウェブオペレーションエンジニアとは直接関係ありません。専門のセキュリティエンジニアがいるわけではないので、セキュリティ会が、情報を収集し、対応をまとめ周知するという役割を担っています。

MySQL-5.6のMRRにデッドロック回避の夢を見る - ichirin2501's diary

MySQLのロックの挙動を調査するために、gdbで解析してたりします。

フルCDNアーキテクチャ実験 / Minami Aoyama Night #1 // Speaker Deck

Minami Aoyama Night#1での発表です。はてなブログのHTTPキャッシュ戦略と、のちにやりたいと思っているフルCDN化についての発表です。

はてなのインフラ環境を自宅で再現する // Speaker Deck

YAPC::Hokkaido 2016での発表です。自宅で動いたから検証済みとかいって本番に投入していく新卒(詐欺)です。

はてなにおけるデータセンター内ネットワークの歴史と今後

DataCenter Networking Conference での発表です。はてなのこれまでのネットワークを振り返るような話になっています。いちWebサービス事業者が今もオンプレでネットワーク運用している例は、昨今では少ないんじゃないでしょうか。資料はそのうち公開されると思います。

10ms以下のレスポンスタイムを支える継続的負荷テスト - taketo957の日記

低レイテンシを求められる広告配信システムでやっている負荷テストCIの話です。負荷テストCIってよくあるアイデアのわりにはあまり見かけないですね。

LinuxのARPとL2スイッチのお話 - masayoshiの日記

LVSのDSRで非対称ルーティングしているときのネットワークのトラブルシューティングの話です。

輪読会

社内でSRE本*1の輪読会を開催し始めました。 世間で言われているエラーバジェットやToilの割合を一定以下に収める努力などが書かれているのはもちろんですが、SREというのは単に定量的アプローチのことだけを指すわけではないということがわかってきています。

その他

法学部生だけどはてなのインフラで4年間バイトした - naokibtn’s blog

長い間おつかれさまでした。

株式会社はてなに入社しました - masayoshiの日記 株式会社はてなに入社しました - taketo957の日記

今年はなんと新卒のWebオペレーションエンジニアが2人も入社しました。

リモートワークにおけるSlack Call活用と終業15分前の雑談 - Hatena Developer Blog

雑談に限らずコミュニケーションの機会を意識的に増やしはじめました。

2016年ウェブオペレーションエンジニアの新卒研修 - Hatena Developer Blog

新卒が2人もきたので、研修し始めました。

東京にいながら仕事のほとんどを京都のエンジニアと一緒にしている私のリモートワークの話 / Hatena Engineer Seminar #6 // Speaker Deck

セミナーでの発表です。Webオペレーションエンジニアは東京でも募集しています。

アプリケーションエンジニアからみたはてなのインフラの話 / Hatena Engineer Seminar #6 // Speaker Deck

セミナーでの発表です。id:KGA さんはWebオペレーションエンジニアではありませんが、アプリケーションエンジニアからみたWebオペレーションエンジニアの話をしてもらいました。

情報処理学会でウェブオペレーション技術について招待講演した話 - ゆううきブログ

なぜか研究者のコミュニティで技術者として講演しました。

ウェブオペレーションエンジニアになるまでの思い出 - ゆううきブログ

Hatena Engineer Seminar #7 での発表内容です。思い出に共感してもらい、Webオペレーションエンジニアに興味をもってもらうという趣旨でした。

サーバとわたし - Words fly away, the written letter remains.

id:tomomii さんは職種としてはエンジニアではありませんが、tomomiiさんらしい感性でとらえた技術の話がたのしいです。

あとがき

はてなのWebオペレーションエンジニアはすごいことをしているのに外へのアウトプットが全然ないなぁと思ったのが、僕がアルバイトにきた2012年のことでした。すごいことをしているのにもったいないと思って、ちまちまとブログを書いたり発表し続けてきたりしました。 今年から自分だけでなくチームメンバーにもアウトプットを促すようになり、アルバイト含めたすべてのWebオペレーションエンジニアがなんらかのアウトプットをした年になりました。

こうして1年俯瞰してみると、はてなのWebオペレーションエンジニアの特色が浮きぼりになります。 ネットワーク、Linux、仮想化、RDBMS、WebサーバといったWebのインフラを支える運用技術(System Engineering)については、自信をもって強いと言えます。しかし、Mackerel以外で、Software Engineeringにより自分たちで最適なシステムをつくっていくという点がまだまだ弱いのが課題だと思っています。

SREに代表されるように、インターネットのインフラの世界でSoftware Engineeringの重要性が高まっており、はてなでもSoftware Engineeringによりシステムの信頼性を高めたいと考えています。 はてなでは、インフラの領域でソフトウェアを書いてみたい、これまでWebアプリケーションエンジニアだったけどインフラの世界に興味があるといった方を募集しています。 もちろん、今のはてなの強みでもあるSystem Engineeringのスキルを生かしたいという方も大歓迎です。

新卒の採用募集もやっています!

*1:Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy, "Site Reliability Engineering: How Google Runs Production Systems", O'Reilly Media, March 2016

はてな「Webオペレーションエンジニア座談会」を公開しました

本日、採用ページの新たなコンテンツとして「Webオペレーションエンジニア座談会」を公開しました。

10年続くサービスを、インフラ技術で支える――Webオペレーションエンジニア座談会 - 株式会社はてな

はてなのインフラチームからid:wtatsuruid:y_uukiid:dekokunid:taketo957の4人が参加し、入社のきっかけやはてなでの働き方、チームの将来像などについて語り合いました。「はてなのインフラチームってどんなふうに仕事をしているの?」という疑問にお答えします。

はてなでは京都・東京の両拠点で、Webオペレーションエンジニアの積極採用を行っています。皆さまのご応募をお待ちしています。

Webオペレーションエンジニア職 - 株式会社はてな