delirious thoughts

by Kentaro Kuribayashi

GMOペパボ株式会社の執行役員CTOに就任しました

昨日(3/21)、GMOペパボ株式会社の執行役員CTO*1に就任しました。昨年8月に技術責任者に就任したのですが、今後はより一層、経営に近い立場で「技術」という切り口において会社の成長に貢献していきたいと思います。

今後やっていくこと

今後やっていきたいことを整理すると、以下の3つになります。

  1. 成長のための技術戦略の策定・実行
  2. 1.を実現するための技術基盤づくり
  3. 1.を実現するための組織づくり

これまでも「GMOペパボ攻勢の裏側にあった「技術的負債を抱えない開発体制づくり」3つの布石 - エンジニアtype」にある通り、あれこれやってきましたが、より踏み込んだ戦略を立て、実行していくつもりです。また、それぞれにおいて各論的にいろいろ考えていることはあるのですが、細かいことをここで述べてもしかたないでしょう。このブログでもこの1年あまり、上記についてあれこれと書いてきたので、是非そちらをご覧いただければと思います。

技術戦略

blog.kentarok.org blog.kentarok.org blog.kentarok.org

技術選択

blog.kentarok.org blog.kentarok.org

技術組織

blog.kentarok.org blog.kentarok.org

ところで

組織づくりにおいて最も重要なのは、いうまでもなく「ひと」です。minneへの大規模投資を始めとする各サービスでの事業遂行に際して、もっと大きく成長するためには、一緒にサービスを作ってくれる仲間が必要です。是非、以下よりご応募ください。

pepabo.com

まずは話を聞いてみたいという方は、ペパランチョン | 採用情報 | GMOペパボ株式会社という機会もご用意しています。ご飯を食べながら、おしゃべりしましょう。

*1:この役職が会社組織上どういう意味については「CTOとか役員とかに関する基本的な知識 - UNIX的なアレ」がわかりやすいと思いますので、気になる方はご参照ください。

全社的に使っているチャットツールをSlackに移行した話

ペパボでは、チャットツールとしてIRCを長らく使っていたのですが、先日、Slackに全面的に移行しました。その話を少し書いてみようと思います。

追記: 社長的にSlackに移行したほうがいい理由 | ペパボ社長ブログというエントリが出ていたので、そちらもご参照ください。

IRCの利用程度

そもそもIRCをどの程度使っていたかというと、職種や役職等を問わず、全スタッフ(アルバイト等も含む)が使っていました。つまり、エンジニアも総務も、マネージャーも社長もみんなIRCにいて、そこでフローのコミュニケーションを行っていたということです(ちなみに、情報のストックや、チャットには向かないような共有にはGitHub Enterpriseを使っています)。また、サーバの状態監視等の様々な通知や、いわゆるChatOps的なこともIRCでやっていたので、人間もbotもとにかくたくさんいて、賑やかな状態です。

IRCの問題

それぐらい活用しまくっていたIRCでしたが、たとえば以下のような問題があったため、解決策を模索していました。

  • ログを共有された形で保存し、検索するのが難しい
  • そのため、過去のチャット上での議論に基づいた発展が難しい
  • マルチデバイス対応が難しい。特にスマホアプリが使いづらい
  • IRCに接続していない間のメンションに気づけない

また、個人でSlackのようなツールを既に使っているひとにとっては、さくさく動いてリッチなUIを提供するアプリ、アイコンの表示されるモダンなチャット体験、豊富なインテグレーションなどの魅力もあり、IRCのシンプルさが、かえって見劣りするものであるとも感じられてきたりもしたのでした。

Slackへの移行プロセス

そこで、Slackに移行を目論む勢力が発生、Slack上にpepaboチームを開設し、自生を始めました。新しもの好きのメンバーたちがあれこれと試していく中で、これなら移行できそうなのでは?という機運が醸成されてきた流れで、経営会議において「移行するぞ!!1」ということになり、もろもろの手続き・計画・利用ルール作り(お金周りや情報セキュリティなどなど)を僕の方で取りまとめ、移行が実施される運びとなりました。その後の流れは以下の通り。

  • 2月25日: 情報セキュリティを担保した上で、移行計画の告知
  • 同日: Slack用のIkachanを作成
  • 2月27日: 開発関連の人々はほぼ移行完了
  • 3月上旬: 通知周りがほぼ移行完了
  • 3月9日: バックオフィスやカスタマーサポートも含めて移行完了
  • 3月18日: 有料プラン開始
  • 同日: 各種インテグレーション完了

以下のグラフを見るとわかる通り、上述のほとんどは3月初頭にはほぼ移行が完了しており、あれだけ活用しまくっていたIRCからの、通知まわりなども含めての移行に、1週間もかからなかったということになります。

f:id:antipop:20150319233255p:plain

これは、それなりのアカウント数(現時点で260超)を持ち、多様な職種、2拠点からなる組織としては、相当のスピードを出せたといえるのではないでしょうか。この会社も長い間いろんなことをやってきており、蓄積されてきた経験に基いて安定した業務を行ってきており、それはそれで非常に素晴らしいことですが、いざ「大きな変化を起こすぞ!」という時にも、こうして全社を上げて素早い動きを見せることができるのは、誇らしいことであるとあらためて思います。

ところで

そんなペパボでは、さらなる飛躍的変化を起こしてくれる、エンジニアを始めとする各職種において、新たな仲間を求めています。是非以下をご覧になって、ご応募ください。ただいるだけですら知らずしらずのうちに(もちろん積極的にアウトプットすればさらに)成長してしまうような意欲的な環境を用意して、お待ちしています。

pepabo.com

メイソンジャー

最近いくつか本が出たりして話題のメイソンジャー、ちょうどガラス製の保存容器をいくつか欲しかったので、流行りモノに手を出してみました。Amazonに出店しているショップで注文したのだけど、大人気っぽくて出荷が延びて、届くまで1ヶ月ほどかかりました。さらには、注文した時は480mlのものが594円だったけど、いま見たら1,050円になっていますね。

とりあえず、まずはサラダを仕込まないと、ってんで、さっそくやってみました。適当に買ってきた野菜を切って、適当に調合したドレッシングを入れたあと、固いものから順番に入れていくだけ。簡単。しかし、どれぐらい入るか正確に読めてなくて、買ったけど入れられなかった野菜がいくつか……。まぁ、それはそれで別の楽しみにとっておこう。

façadeでGitのようなサブコマンドをディスパッチする

Gitには、git fooと実行すると、$PATH内のgit-fooを実行するというサブコマンドの機能がある。そのため、その規約に則りさえすれば、Gitのサブコマンドをいろんな言語で書けるというメリットがある。それを簡単に実現するために、façadeというごく単純なライブラリを書いた。

使い方

これを使うと以下のように書くだけで、コマンド名がyour-commandだったとして、your-command foo bar bazと実行すると、your-command-foo bar bazという呼び出しに変わる。

package main

import (
    "github.com/pepabo/facade"
)

func main() {
    facade.Run()
}

なぜ作ったか

ある目的に利用するツール群があるとして(たとえばEC2を操作するような各種コマンド群)、以下のような問題を解消するためである。

  1. ひとつの言語に限らず、実装する人々が得意な言語によって、それらのツールを書きたい
  2. しかし、それらがフラットな名前でだらだらーっとあると、見た目に悪い感じがする
  3. また、どのツールでも使うような、たとえば色付けされたロギングだとかそういうのを提供する際に、各コマンドでいちいち実装していると統一感がなくてよくない

そのため、入り口 = dispatcherのみを提供するライブラリとしてfaçadeを作った。これにより、統一的な名前、機能を提供できるようになった。

SUZURI APIとNW.js(旧node-webkit)を使ってTシャツを作る

オリジナルグッズを手軽に作成・販売 | SUZURI(スズリ)に、APIができました。SUZURI Developer Centerから詳細を見ることができます。さっそく遊んでみようってんで、NW.js(旧node-webkit)を使って、Tシャツを作るということを試みてみました。

コードが雑過ぎてアレなんですが、気にしません。

起動方法

  1. NW.js(旧node-webkit)をインストールします。
  2. Macの場合、以下のようにして起動します。
$ /Applications/nwjs.app/Contents/MacOS/nwjs . API_TOKEN

API_TOKENは、SUZURI Developer Centerから取得してください。

画面

こんな感じの画面が出るので、

f:id:antipop:20150312081829p:plain

ボタンを適当に押すと、SUZURI上でTシャツが作成されて、以下のように結果が表示されます。

f:id:antipop:20150312081856p:plain

んでもって、こんな感じのURLで実際にTシャツができて、販売できます。

まとめ

簡単に使えて楽しいですね。是非みなさんも、SUZURI APIを使って遊んでみてください。

新刊『スクラム実践入門』の紹介、あるいは、日本のソフトウェア開発の夜明け

発端は確か一昨年のCROSSで、@hsbtさん、稲尾さんの間で話が盛り上がったのが最初だったと記憶しているから、あれから約2年、強力なメンバーで共同執筆した『スクラム実践入門──成果を生み出すアジャイル開発プロセス』が、いよいよ3/18に刊行される。 追記: 3/18に発売されました。 Amazonのリンクは以下。電子書籍をご希望の方は、版元のサイトで発売と同時に販売されるはずなので、そちらをお待ちください。

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

スクラムに関する類書は既にたくさん出ているし、それぞれに素晴らしい本ばかりで、いまさら屋上屋を架す必要もなかろうという気持ちがないではなかった。しかしそれでもなお、なぜ我々があえてこの本の執筆に至ったか。それは、スクラムの実践者としていまやそれなりの割合を占めるだろうWebサービス事業者としての観点から書かれた本がなかったからだ。では、その「観点」とはどういうことか。

  • Webサービスは、継続性をその特徴としている。すなわち、一度出せば終わりではなく、長い間価値を提供し続けるものである
  • また、求められる水準は年々複雑化しており、それを達成するための技術的な条件はいまや非常に専門家し、高度なものになっている
  • さらには、不特定多数のコンシューマ向けWebサービスでは顧客要求が不定であるため、何を作るべきかが常に変化し続ける

Webサービスの開発者は、上記のような環境下において、日々仕事をしている。そして、我々の経験によると、そうした現場でもまたスクラムは役に立ち得るものであると確信している。楽しくも、時に苦しみながら、しかし一貫してWebに夢を持ち続けていたのであればこそより良いサービスを目指して研鑽に勤しんできた我々の経験をひと通りとりまとめ、後続の踏み石となるべく、こうして一冊をものしたのだった。

上記の、共著者のひとりである原田勝信さんによるスライドにもある通り、第1章〜第5章の「理論編」、第6章〜第8章の「事例編」、そして第9章〜第12章の「あるある編」という内容で、スクラムに興味を持ち始めた方にはもちろんのこと、かなりの手練れにとってすらもなお、得るところの多い本になったと自負している。Webサービス開発に携わるすべての人々、すなわち、エンジニアやデザイナはもとより、ディレクターやマネージャーなどにとって、チーム開発の前提となる知識・ボキャブラリーを提供する本になるだろう。

我々も、独力でここまできたのではなかった。多くの先達に導かれてやってきたのだ。いまその恩を、この本の上梓をもって幾分かは返すことができたように思う。

日本のソフトウェア開発の夜明けが、いまここに始まる。

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

gRPCでgdbmにネットワークインタフェイスを持たせる

先日、HTTP/2とProtocol BuffersをベースにしたRPCフレームワークgRPCがリリースされた。

Microservicesがなんちゃらいわれる昨今だが、その実現のためには、設計面におけるベストプラクティスはもとより、実装面においても課題がある。すなわち、サービス間でどのようにオーバーヘッドが少なく、帯域を浪費しない通信を実現するかということ。そんな折Googleが、上記のリンク先にある通り「うちらめっちゃMicroservicesだし」ってんで、まさに「これだ!」という技術スタックでいい感じのものを出してくれた。

gdbmにRPCしてみる

とりあえず試してみたいので、簡単にできそうな例として、gdbmにネットワークインタフェイスをもたせてRPCしてみる、ってのをやってみた。

kentaro/grpc-gdbm · GitHub

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

Thriftとかああいうのを触ったことがあるひとにはお馴染みのIDL(Interface Definition Language)があって、gRPCの場合はProtocol Buffersを用いて、こんな感じで書く。以下は、gdbmに対して、Insert, Replace, FetchというRPCを定義している。Protocol Buffersを使うぐらいなのでデータ量-awareな感じだろうから、ほんとは以下のRequestの定義をもっと厳密にわけた方がいいと思うけど、例なので深く考えない。

syntax = "proto3";

package gdbm;

service Gdbm {
        rpc Insert (Request) returns (Entry) {}
        rpc Replace (Request) returns (Entry) {}
        rpc Fetch (Request) returns (Entry) {}
}

message Request {
        string key = 1;
        string value = 2;
}

message Entry {
        string key = 1;
        string value = 2;
}

んでもって、この定義からRPCへのクライアントとサーバのコードを生成する。

$ protoc -I ./protos ./protos/gdbm.proto --go_out=plugins=grpc:gdbm

生成された内容は以下の通り:

サーバとクライアントを書く

あとはそれを使ってなんか適当に書いていくだけ。IDLで定義したInsert, Replace, Fetchを実装したstructを、上記で生成されたpb.RegisterGdbmServer()にわたしてやると、RPCをいい感じに受け付けるようになる(生成されたコードに、そういうinterfaceが定義されている)。

サーバ:

package main

import (
    "flag"
    "fmt"
    "log"
    "net"

    "github.com/cfdrake/go-gdbm"
    pb "github.com/kentaro/grpc-gdbm/gdbm"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

var port int
var file string

func init() {
    flag.IntVar(&port, "port", 50051, "port number")
    flag.StringVar(&file, "file", "grpc.gdbm", "gdbm file name")
    flag.Parse()
}

type server struct {
    Db *gdbm.Database
}

func (s *server) Insert(ctx context.Context, in *pb.Request) (*pb.Entry, error) {
    err := s.Db.Insert(in.Key, in.Value)
    return &pb.Entry{Key: in.Key, Value: in.Value}, err
}

func (s *server) Replace(ctx context.Context, in *pb.Request) (*pb.Entry, error) {
    err := s.Db.Replace(in.Key, in.Value)
    return &pb.Entry{Key: in.Key, Value: in.Value}, err
}

func (s *server) Fetch(ctx context.Context, in *pb.Request) (*pb.Entry, error) {
    value, err := s.Db.Fetch(in.Key)
    return &pb.Entry{Key: in.Key, Value: value}, err
}

func main() {
    lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    db, err := gdbm.Open(file, "c")
    if err != nil {
        log.Panicf("couldn't open db: %s", err)
    }
    defer db.Close()

    s := grpc.NewServer()
    pb.RegisterGdbmServer(s, &server{Db: db})
    s.Serve(lis)
}

クライアントは特に述べるまでもない感じ。この例の場合に普通に使うなら、生成されたコードを使っていい感じのAPIを持つライブラリを作って、それを使うことになるだろう。

package main

import (
    "flag"
    "fmt"
    pb "github.com/kentaro/grpc-gdbm/gdbm"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
    "log"
)

var port int
var key string
var value string

func init() {
    flag.IntVar(&port, "port", 50051, "port number")
    flag.StringVar(&key, "key", "key", "key name")
    flag.StringVar(&value, "value", "value", "value for key")
    flag.Parse()
}

func main() {
    conn, err := grpc.Dial(fmt.Sprintf("localhost:%d", port))

    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    c := pb.NewGdbmClient(conn)

    r, err := c.Replace(context.Background(), &pb.Request{Key: key, Value: value})
    if err != nil {
        log.Fatalf("gdbm error: %v", err)
    }

    r, err = c.Fetch(context.Background(), &pb.Request{Key: key})
    log.Printf("value for %s: %s", key, r.Value)
}

RPCしてみる

そしたら、あとはサーバとクライアントを使ってRPCできる。

サーバを起動する:

$ go run server/main.go

-key, -valueの引数で指定した値を入れたり出したりするだけのクライアント:

$ go run client/main.go -key foo -value bar
2015/03/03 01:11:12 value for foo: bar

簡単ですね。

使いどころ

この例で示したような、6〜7年前とかにThriftとか使っていた頃のようなユースケースにもあてはまるんだろうけど、いまだとまさにMicroservices用とかStreamingとかに使う感じになるんだろう。というか、そうでないとHTTP/2なうれしさがあんまり見いだせないだろうし。

ともあれ、当時だといろいろとしんどかった記憶があるけれども、いまだと例でも利用したGoもあるしHTTP/2もあるし、いろいろ環境は整っているなという感じがする。