社内ハッカソンイベント Raksul Hack Week #1 を開催中です

RakSul Hack Week Logo

エンジニアの二串です。

最近少しづつ朝晩が冷えるようになってきて秋の到来を感じますね。さて、秋といえばハッカソンですよね(!!?)

というわけで今週、ラクスルでは社内ハッカソンイベント「Raksul Hack Week #1」 を開催しています。

RakSul Hack Weekとは?

もともと月に1日、エンジニアは直接的な業務を離れ自由に開発をしていい Hack It Day という制度がありました。今回はそれを拡張し、1週間に渡って、全社的に(エンジニア、プロマネ、デザイナー混ぜて)やろうよ!というイベントです。さらりと書きましたが、1週間普段の開発を止めて、自由な発想でおもいっきりやってみる企画になります。今回が記念すべき(?)第1回目となります!!!

今回はやりたいことを事前にメンバーから集めて、出てきたアイデアをベースに数名1チームでチームを組んで、チーム=プロジェクトを作って取り組む方式を採用しました。

今週はシルバーウィークで月曜がお休みなので火曜から金曜まで計4日間の開催し、最終日にはチームごとの成果発表を開催します。成果発表会では、参加者の他、非参加者(ビジネスやカスタマーサポート)も交えての会となります。

楽しく作戦会議中の様子

各チームで作業が進んでます

今回は1週間ということで普段なかなか試せない技術スタックを試してるチームも多く、参加者達はそれぞれ盛り上がって来ているようです。

どんなことをやってるの?

例えば、

  • AWS lambda を使ってのFAXとウェブをつなげるサービスの開発
  • Nuxt.js + TypeScript で作るSlackと連携したウェブサービス
  • AIによる注文審査の自動化システム

などなど…. 技術領域も解決する課題も様々。今回は12チーム、総勢41名が参加しています。

もくもく作業中!?

さて、どんな成果物ができるでしょうか!!? 今から楽しみです。

また詳細はレポートします。

wifi打刻システムをつくった話

出社時/退社時の打刻ってとても面倒くさくないですか?

わかっていてもついつい打刻するのを忘れてしまいます。そして月末の勤怠締めで打刻忘れの箇所を手動で1つずついれていく。。とても非生産的ですね。

そこでシステム的にこの問題を解決するべく、メルカリの記事を参考にwifi打刻システムをつくりました。

wifi打刻システムとは社員さんが持っている端末(携帯やPC)がwifiに繋がった時に出社打刻をし、最後にwifiに繋がっていた時間を退社時刻として退社打刻を行うシステムです。

それではwifi打刻システムを作る方法について説明していきます。大きくわけて3つのステップに分けることができます。

  • 社員が持っている端末がwifiに繋がっていることを検知する
  • wifiに繋がった端末から社員を特定する
  • wifiに繋がった時に出社or退社の打刻をする

社員が持っている端末がwifiに繋がっていることを検知する

携帯やPCなどの端末にはMac Addressという端末毎に固有な物理アドレスが割り振られています。

wifiルーターに繋がっている端末のMac Addressを取得することでwifiに繋がっていることを検知しました。

Mac Address取得する方法はいくつかありますが、今回はsnmpwalkというコマンドを使いました。

ルーターと同じネットワーク内にあるサーバー上でsnmpwalkコマンドを打つと接続している端末の情報が得られます。

あとはその出力をparseすることでwifiに接続している機器のMac addressの一覧を取得しました。

wifiに繋がっている端末から社員を特定する

wifiに繋がっている端末のMac Addressの一覧が取得できたので、どのMac Addressがどの社員のものなのか特定する必要があります。

今回は単純にMac Addressと社員番号を紐づけるデータベースを用意しました。

どのMac Addressがどの社員のものなのかはwifi打刻の利用申請を出す際にMac Addressも教えてもらうようにしました。

iPhone/AndroidのMac Addressの調べ方は以下のサイトが参考になると思います。

これでMac Addressの一覧を社員番号の一覧に変換することができました。

wifiに繋がった時に出社or退社の打刻をする

社員番号の一覧が取得できるようになったので、後は出社or退社の判定をして打刻をすればよさそうです。

判定を行うために社員番号を取得するスクリプトをバッチで数分間隔で実行し、wifiに繋がっている社員番号一覧を取得した際に、その時の時刻をwifiに接続していた時刻として社員番号と共に各社員番号について記録しておきます。

{
  1: { # 社員番号:1の人がいつwifiに接続していたかを記録
    connected_at: "2018-09-05 14:31:52 +0900"
  },
  2: { # 社員番号:2の人がいつwifiに接続していたかを記録
    connected_at: "2018-09-05 14:31:52 +0900"
  },
}

出社についてはその日初めてwifiに繋がった場合に、その時刻を出社として打刻すればよさそうです。

退社については最後に接続した時刻と次にwifiに接続した時刻が一定時間以上離れていた場合に退社時刻として打刻するようにしました。こうすることでランチなどで外出してwifiが切れた時でも退社打刻されないようにしました。

ラクスルの勤怠システムにはAPIで打刻する機能があったので出社or退社と判断された時にAPIを使って打刻を行いました。また打刻されたかどうかわかるようにAPIで打刻した際にslackでDMを送って通知するようにしました。

これでwifiに繋がった時に出社/退社打刻してくれるwifi打刻システムが出来上がりました。

まとめ

打刻忘れや打刻修正などの無駄な作業をなくすべくwifi打刻システムをつくった話を紹介しました。

実際にwifi打刻を使っている社員さん達から「すごい便利」「快適になった」と言った声も頂いています。wifi打刻の仕組み自体はとても簡単なので、やろうと思えばすぐに導入できると思います。

打刻が面倒だと感じたら導入を検討してみてはいかがでしょうか。

ラクスルではエンジニアを積極採用しています

ラクスルに興味を持たれた方は是非一度オフィスに遊びにきてください!

宛名印刷ができる年賀状・喪中はがきをリリースしました

はじめに

ラクスルでエンジニアをしている藤田です。
先月、「年賀状・喪中はがき」という商品をリリースしました。
ラクスルで扱っている印刷サービスは基本的に、PDF等でアップロードされた印刷データを対象の商品(チラシや名刺など)に印刷してお客様へお届けするというものです。
今回リリースした商品は宛名印刷という機能があり、印刷データと一緒に宛名リストをアップロードしてもらい、印刷データと共にそれぞれの宛名をはがきに印刷します。他の商品では全く同じ印刷物が注文された部数だけ出来上がるのに対して、宛名印刷では一つ一つの印刷物が宛名の箇所だけ異なる内容になる点が特徴です。
一見するとシンプルに思われるこの機能ですが、実際に開発してみると意外と奥が深く面白かったので紹介したいと思います。

宛名印刷の難しさ

宛名印刷の難しさは「どうやって宛名を違和感なく宛名面にマッピングするか」にあります。組版処理とも呼ばれます。
下の画像を見ていただくと伝わるかと思うのですが、役職・部署の有無や文字数などで宛名面のどこに印刷するかが大きく変わります。
そのため、様々なパターンを考慮する必要があり必然的に開発も難しくなります。

今回はこのよう組版処理を実装するにあたって、開発スピード等を考慮して既成の組版ソフトを利用する方針としました。このソフトはWindows上でしか動作しないため、別途windowsサーバーをたてる必要がありました。

システム概要

少し簡略化していますが、組版処理に関連するシステムの概要図は上記のようになっており、次の通り処理されていきます。上述の組版ソフトは⑥で使用しており、SQSからキューを取得したりS3にアップロードしたりといった周辺の処理はWindowsとも相性が良いGolangで開発しました。

1. ユーザーが印刷データと宛名リスト(CSV)をアップロード
2. 印刷データと宛名リストをS3に保存
3. SQSに組版処理をエンキュー
4. SQSからキューを取得
5. S3から印刷データと宛名リストを取得
6. 組版処理を実施
7. 処理結果ファイルをS3に保存

Webアプリケーションと組版ソフトが動作するWindows Serverを繋げる方法として、Amazon SQSを利用しました。Windows Server上にAPIサーバーをたてる方法もありますが、やや開発コストが増える点と、宛名リストの件数によっては組版ソフトの処理に時間がかかるためキューイングが必要だったこともあり、SQSを採用しました。

マニアックな機能: CIDチェック

今回、開発した機能の中で面白かったものがCIDチェックです。CIDとはアドビ社が定めている文字ごとに一意に振られる番号のことで、フォントの文字を識別するために用いられます。例えば、フォントでは異体字の字形を区別する必要がありますが、Unicode等の一般的な文字コードでは同じコードが割り当てられていることがあるため、CIDが利用されます。
宛名印刷では、宛名に用いられるフォントとして正楷書CB1、リュウミンなど4種類から選択することができます。これらのフォントはカバーしているCIDの範囲以外の文字には使用することができないため、宛名リストで入力された文字が範囲内に含まれているかどうかをチェックすることが必要です。
CIDチェックの実装方法ですが、

1. 入力された文字に紐づくCIDを取得する
2. 取得したCIDが範囲内に含まれるかチェック

という順序でチェックをしていきます。
私が探した範囲ではRubyのライブラリ(CIDチェックはRailsアプリ内で行います)で文字列からCIDを取得するようなものはなかったため、UTF-8のコードとCIDをマッピングしたファイルを作成してUTF-8からCIDを引けるようにしました。
幸い、アドビ社が提供しているcid2code.txtというファイルにCIDと主な文字コードとの対応表がありましたので、このファイルを利用することでマッピングファイルを作成することができました。
細かい話になりますが、最終的に実装は下記のようになりました。

# app/validators/adobe_japan13_validator.rb

class AdobeJapan13Validator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.nil?
    chars = invalid_chars(value)
    record.errors.add(attribute, :invalid_character, invalid_chars: chars.uniq.join) if chars.present?
  end

  class << self
    def valid_strings_map
      return @valid_strings_map if @valid_strings_map
      @valid_strings_map = {}
      File.open(Rails.root.join('config', 'adobe_japan13.dat'), 'rb') do |f|
        f.each_line do |line|
          line.chomp!
          _cid, utf8 = line.split("\t")
          @valid_strings_map[utf8] = true
        end
      end
      @valid_strings_map
    end
  end

  private

  def invalid_chars(target_string)
    target_string.each_char.reject do |c|
      utf8 = c.unpack1('H*')
      self.class.valid_strings_map.key?(utf8)
    end
  end
end

バリデーターの中で読み込んでいる adobe_japan13.dat がマッピングファイルになっており、次のような内容になっています。左側の数字がCID、右側がUTF-8に対応しています。

# config/adobe_japan13.dat
1	20
2	21
3	22
4	23
5	24
6	25
7	26
8	27
9	28
10	29
11	2a
12	2b
13	2c
14	e28091
# 以下略

おわりに

この記事では宛名印刷という開発案件について紹介しました。
組版処理やCIDチェックといったものは印刷サービスならではで、他の会社ではあまり経験できないラクスルらしいテーマを紹介できたかなと思っています。

そうだ スピードチェック入稿のテストを自動化しよう

ラクスルのサーバサイドエンジニア 加藤です。

今回はスピードチェック入稿(テスト対象が印刷用ファイルの場合)の自動テストについて書いてみたいと思います。

再びスピードチェック入稿とは

チラシや名刺などの印刷をインターネットで注文したことのある方はいらっしゃいますか。

印刷したいものを選んで購入し、自分で用意した印刷データをアップロードして待つと、チラシや名刺などが届きます。通常の通販サイトと違うのは、自分で印刷したいデータを用意し、アップロードする作業です。さらに入稿データはラクスルでチェックし、印刷に適した形式に変換されます。

ラクスルでは、昨年8月末にそれまでオペレータが手動で行ってきたこの工程を自動化、スピードチェック入稿をリリースしました。それまで、1日以上かかってしまうこともあったデータチェックが、その場で完了。印刷物のお届けまでの日数が想定よりかかってしまうということもなくなり、多くのお客様に使われるようになりました。

リリースまでの過程は、スピードチェック入稿リリース秘話でご紹介させていただきました。

スピードチェック入稿のその後

さて、スピードチェック入稿は、その後もどんどん進化してきました。

1. 対応商品の拡大
最初は、チラシ・フライヤーと名刺だけだった対応商品に、ポスター/ポストカード/カード/チラシ折加工/折パンフレットが加わりました。

2. 入稿ファイル形式の追加
入稿ファイル形式も最初はPDFのみでしたが、ai/jpg/png/tiffでも入稿できるようになりました。また、ラクスルで提供しているWEBブラウザから利用できる無料のデザインソフト「オンラインデザイン」で作成していただいたデータも入稿することができます。

3. UXの改善
面裏の入稿原稿向き、折の開き向きなどを実際の印刷物により近い形でご確認していただくために、仕上がりプレビューが生まれました。実際に、ひっくり返したり、開いたり閉じたりして仕上がりを確認することができます。

折加工商品の仕上がりプレビュー

さて、様々な機能追加があると、大変なのがテストです。

ファイルの変換が入るために、テストを自動化しようにも、通常のWebテストのフレームワークだけでは対応できません。悩んでいるうちにも開発は進み、リリースのたびにプロジェクトメンバーがかなりの時間をかけて、データを手動でチェックしてテストをしていました。また、テストの実施もれが発生してしまうことがありました。これでは、チームとして自信を持って開発・リリースすることができません。

テストを自動化するぞ!

なんとかしなきゃとディスカッションしていたところ、「正常リリースで生成された印刷データと変換方法に変更を加えた後に生成した印刷データを、画像に変換して比較したらいいのではないか」というアイデアと、実際にImageMagicのcompareコマンドで検証結果がチーム内でシェアされました。

印刷データ画像

差分なし

差分あり

変換方法を変えて差分ができた場合は、差分箇所が赤く表示されます。これなら、一目で問題に気づけそうです!

このアイデアをとっかかりに、さらに印刷データのファイルに関してテストしたい項目を整理してみました。

1. ファイルの規格、各BOX(*)のサイズ、カラーが注文情報と比較して正しいこと
2. 問題のあるファイルに対して正しくエラーが返されていること
3. 変更前後の印刷データの画像差分がないこと、もしくは差分が妥当であると確認できること

* ドキュメントの用紙サイズ、印刷用の裁ち落としや仕上がりサイズの定義

そして、実際にテストを開発に組み込んでいくために、非エンジニアでも気軽にテストを実施したいと考えました。それぞれテストファイルが30個だとしても、この3項目に対してテストすると3倍の90項目。テストが大変だという理由で改善が進まないのは残念です。

なるべく早く問題に気づけるようにする

早速、設計に取りかかりました。

自動テストの場合は、社内ツールでユーザは自分も含め同じプロジェクトのメンバーです。要件はユーザ向けの機能と違って自由に決められますが、今回は開発がスムーズに進むようにするためなので「開発のなるべく早い段階で問題に気づけるような仕組みを作る」を指針にしました。

スピードチェック入稿のシステムは大きく3つのレイヤーに分かれています。

・フロント:データチェック用のAPIを呼び出し結果を描画
・データチェック用のAPI: フロントから受け取ったリクエストを受けてジョブをキューイング
・バックエンドジョブ:データチェックファイル変換を実施

シンプルにするために、今回の3項目のテストの対象はバックエンドジョブに絞りました。

システム構成

先ほどの指針にしたがって、1. ファイルの規格のテストに関しては、QA環境でスピードデータチェック入稿が使われると必ずジョブ内で自動で実行され、問題が発見されればslackに通知されるようにしました。

 

ファイルアップロード後の処理の流れ

上記の処理の流れの中で、サムネイルの生成が終わったらステータスは終了にして、フロントが描画できるような状態にしつつ、データチェックエンジンのチェック用のスクリプトが走るような作りです。

2. エラーのテスト3. 画像比較テスト に関しては、実行するとしばらくQA環境のジョブを占有してしまうので、実行タイミングをコントロールできるように、手動でslackから実行できるようにしました。

実行するとテストケースのYAMLから、上記の処理のファイル検証〜サムネイル生成を行うジョブをまとめて生成、結果チェックまたは画像比較が順次実行されます。画像比較テストの場合はテストケースが何十個もあるため、期待画像を一括に生成するコマンドも用意。テストケースの更新の手間も軽減しました。

テストの結果も、既存ツールに表示しようかと思いましたが、もう少し要件があったため、以下の画像のように、Datacheck APIの管理画面に表示しています。

画像比較テストの結果一覧(差分がない場合)

 

画像比較テストの結果一覧(差分がある場合)

これで1日〜2日かかっていたテスト作業が、30分以内で実施できるようになりました!
さらにミスもなくなり自信を持ってリリースすることができるように。ファイルの処理で処理フローに変更が必要になって試行錯誤することがあっても、すぐに確認できると開発効率は上がりますし、様々な改善のアイデアも湧いてきます。

自動テストの開発後、スピードチェック入稿当初からやりたかった複雑な処理変更や細かい改善を無事にリリースすることができました。

自動テストを使い続ける

自動テストは、テスト自体のメンテナンスも必要ですね。

今回は同じリポジトリにテストケースの定義を含めたため、通常のWebテストフレームワークと同じように機能修正のPull Requestに含めてテストの変更、追加を行なっています。

自動テストに関するREADMEも用意しメンバーにシェア。エンジニアだけでなく、データチェックのエンジンの設定メンバーも、テストケースの変更・追加を行なって、テストを最新の状態に保っています。

まとめ

スピードチェック入稿の印刷用ファイルを対象にテストを自動化しました。

「開発のなるべく早い段階で問題に気づけるような仕組みを作る」を指針に3つの項目のテストが短時間に実施可能に。これにより、すぐにミスに気づけるようになり、開発効率も向上しました。

テストの自動化は後回しになってきましたが、スピードチェック入稿が進化していく上で重要な施策だったと思っていますし、早速その効果を実感することができました。

ラクスルでは、絶賛エンジニア募集中です。

「仕組みを変えれば世界はもっとよくなる」

ユーザ価値をさらに向上させつつ、より社内外のサービスと繋がっていくプラットホームを開発していきたいエンジニアを募集しています。是非一度オフィスに遊びにきてください!

運用中のRailsプロジェクトをなめらかに複数DB化した話

エンジニアの二串です。

ラクスルのRailsのプロジェクトではデータベースとして Amazon Aurora(MySQL) を採用しています。そしてO/Rマッパーとして当然ActiveRecordを使っています。

さて、ActiveRecordを使っていて悩むのが複数DBの接続ですがみなさんはどうしていますか? ActiveRecordは標準では1つのデータベースにしか接続できないので、複数の異なるデータベースサーバや、マスター・リードレプリカの接続を切り替えるには工夫が必要です。しかし、世の中には素晴らしい方々がいて複数DB切り替えを可能にするgemが提供されています。

今回はそれらgemの中からSwitchPointを採用し、運用中のRailsプロジェクトになめらかに導入したときの経緯と方針、さらに具体設定を紹介します。

確認したバージョンは以下のとおりです

  • Rails 5.1.5
  • Ruby 2.4.2
  • switch_point 0.8.0
  • arproxy 0.2.3

最初からまとめ

記事では以下のことを書いています。

  • 運用中のRailsプロジェクトにSwitchPointを導入し複数DB化しました
  • マスター接続をデフォルトにし、オプショナルでリードレプリカへ接続するようにしました
  • 複数DB化した後も、いままでの素のRails(シングルDB運用)での開発のスピード感を損なわないよう、工夫をしました

導入前の事情

複数DB化の背景を少しだけお伝えしますと、今回のRailsプロジェクトは元々はphpで書かれた管理画面の刷新目的でスタートしたプロジェクトでした(詳しい事情は過去の記事でも触れています)。しばらくの月日の後、プロジェクトがいい感じに育ちまして表側の機能も提供するまでに進化しました。現在では、そうだ、ラクスルを作り直そう!でも触れられているRaksul Platform Projectの1コンポーネントを担っています。

今回の対応はその表側の機能も提供することになったフェーズでの話で、状況は以下のとおりでした。

  • これまで管理画面のみを提供していたので、マスターのみの接続で割り切ってた
  • 今後、raksul.comのパブリックな機能も提供することになった
  • read mostly, write sometimesなサイト特性上、参照系はリードレプリカへ逃したほうがベターだが、マスターに向けてしまっても当面は捌ける規模感
  • とはいえ、マスターの負荷を増加させないようリードレプリカへの接続も用意しておきたい

このような経緯で複数DB化の対応を入れることにしました。

複数DB化によるマイナス面の考慮と導入方針

これまでの経験上、複数DB化することにより以後の開発スピードが落ちたり、運用工数が増えるケースがあることを知っていました。具体的には、

  • 実装工数増加(この save! はマスターに接続して、次はSELECTするからリードレプリカに接続して…と考えたりする工数)
  • コードの見通しが悪くなる(SwitchPointの場合 with_readonly { with_writable { ... } } のようにブロックで囲ってネストするので)
  • テストの実装工数(同上 + FactoryBotで作成する際の考慮等)
  • レプリ遅延の考慮が発生する (INSERT直後にリードレプリカ側でSELECTして空振ったら、マスターにフォールバックして参照する、レプリ遅延を考慮したCI環境にするかどうか、etc..)

等々。

これらのデメリットを受け入れるというのも一つのやり方ですが、そうはしたくありませんでした。なるべく開発スピードを素のRailsでの感覚のまま、これまでのシングルDBオンリーでの開発のスピード感のままに、複数DB化できないだろうか、という点をとても大事にしました。

また、改修にあたっては、既に管理画面向け機能がたくさんあるのでコードの修正範囲は最小にしようとおもいました。

そこで、改修にあたって以下の方針を立てました。

  • gemはSwitchPointを使う
  • マスターDBデフォルト、リードレプリカ参照をオプショナル
  • コントローラのアクション単位で参照を切り替る
  • レプリ遅延を考慮したコードは書かないようにする
  • RAILS_ENV=testではシングルDBで
  • マスター・リードレプリカ接続状況をログに記録する

以下でそれぞれ詳細説明します。

SwitchPoint

SwitchPoint 1択でした。理由は、私の前職のプロジェクトで使っていて問題なく動いているのを知っていたのと、そのときに内部実装を大体把握していたからでした。よって他のgemは検討しませんでした。

マスターDBデフォルト、リードレプリカ参照オプショナル

SwitchPointのREADMEを読み進めると、モデルクラスはマスター、リードレプリカどちらに接続するかを with_readonly {} または with_writable {} ブロックでどちらも指定した例に見られます。この方針で進めると、我々の場合既存の管理画面のコントローラをすべて修正しなければならなくなってしまいます。コードの改修量は最小にしたかったのでこれは避けたい。

そこで、まず、with_readonly {}with_writable {} も指定せずにActiveRecordでクエリを実行した場合はデフォルトでマスターに接続されるようします。そして重いクエリが実行されるページやアクセスが多いページでは都度 .with_readonly {} を使ってリードレプリカへ接続させるようにしました。

# こういう処理が既にあって...
Order.find(params[:id]).update!(order_params)

# 素で SwitchPoint を導入すると以下のような書き換えが必要だが...
order = nil
order = Order.with_readonly { Order.find(params[:id] }
Order.with_writable { order.update!(order_params)

# そうではなくマスター接続をデフォルトにすれば、既存コードを書き換えずに済む
Order.find(params[:id]).update!(order_params)

これを実現するにはいくつか設定が必要です。READMEにはあまり書かれていなかったので内部実装も読んでます。

database.yml

# writable 系は Rails 標準のネーミング development, production, etc とする.
# これは https://github.com/eagletmt/switch_point/issues/16 の通りで、標準のネーミングの設定が無いと
# Rails が起動しないケースに遭遇したため.
development:
  # 接続情報(略)
  database: raksul_development
development_raksul_readonly:
  # 接続情報(略)
  database: raksul_development

test:
  # 接続情報(略)
  database: raksul_test
test_raksul_readonly:
  # 接続情報(略)
  database: raksul_test

production:
  # 接続情報(略)
production_raksul_readonly:
  # 接続情報(略)
  • マスターの接続情報はRails標準のdevelopment,test,productionに定義する
  • リードレプリカの接続情報は#{Rails.env}_raksul_readonly に定義する

switch_pointの設定

SwitchPointでマスターDBへの接続をデフォルトにするには SwitchPoint.writable!(接続シンボル名)をアプリケーション初期化フェースでcallします。

# config/initializers/switch_point.rb

SwitchPoint.configure do |config|
  raksul_config = {
    readonly: :"#{Rails.env}_raksul_readonly",
    writable: :"#{Rails.env}"
  }
  if Rails.env.test?
    # 通常SwitchPointは2本コネクションを作る(readとwrite).
    # しかし、database cleanerでtransaction strategyを使っているとテストがfailする.
    # なぜなら、transactionのbeginはwriteコネクションでcallされ、
    # SELECT は read コネクションで呼ばれるが、
    # FactoryBotで作られたレコードはcommitされるまでSELECTしても参照できないのでテストが成立しない.
    #
    # この問題を解決する2つの方法:
    #   1. RAILS_ENV=testでのみSwitchPointのコネクションを1本にする
    #   2. transaction以外のstragegy(truncation or deletion)に変更する
    #
    # 我々は1を選択した。2の方法ではテストが遅くなったため。
    #
    # 1をやるには、readonlyのコネクション設定を消すことで実現できる.
    # こうするとSwitchPointはwritableコネクションにフォールバックする挙動
    # ref https://github.com/eagletmt/switch_point/blob/v0.8.0/lib/switch_point/proxy.rb#L131
    raksul_config.delete(:readonly)
  end
  config.define_switch_point :raksul, raksul_config
end
# Change @global_model of the proxy for raksul :writable
# ブロック指定なしの場合の挙動を writable にする
SwitchPoint.writable!(:raksul)


# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
 self.abstract_class = true

 # モデルのSwitchPoint組み込み
 use_switch_point :raksul
end

なお、一点database_cleanerでtransaction strategyを使っていたので上のコメントの通りコネクションを1本にする対策を入れました。

これで既存のコードは修正せずに済みます。

ではリードレプリカを参照したい場合には with_readonly { } のブロックを書かなければならないのか? これも次の方法で楽をします。

コントローラのアクション単位でリードレプリカに切り替える

開発ポリシとして、コントローラのアクション単位でリードレプリカへ接続を向けるようにします。

例えば、OrdersControllerの #index, #show, #new, #edit ではDBへの書き込みはなく参照しか発生しない、というケースは良くあることかとおもいます。なので、around_action filter を使って with_readonly {} をcallしてあげます。そうすることで、リードレプリカ参照においても with_readonly {} のブロックを意識することなく filter を設定するだけで済みます。ブロックがないのでコードの見通しが損なわれません。

class ApplicationController < ActionController::Base
  private

  def with_readonly
    ApplicationRecord.with_readonly { yield }
  end
end

class OrdersController < ApplicationController
  around_action :with_readonly, only: %i[index]

  def index
    # アクション内で .with_readonly { .. } を意識しなくて済む
    @orders = Order.all.order(:id)
  end
end

中には参照系のペーシだけど別途行動ログを書き込みたいといった場合もあるかもしれませんが、そういうケースではそのそのアクションではリードレプリカへ接続させずマスターへ接続させる、で割り切ります。

レプリ遅延は考慮しないコードを書く

1つのアクション内でいくつかレコードをSELECTしINSERT or UPDATEする時、理想的には参照はリードレプリカへ、書き込みはマスターへ、と細かく切り替えるのがDB負荷を考えると理想的です。ただ、レプリ遅延により書き込み直後のリードレプリカ側のSELECTが空振って想定してなかったバグが発生したり、またその対策としてマスターへフォールバックさせるコードを書いたり…という経験がある方もいるとおもいます。このような状況では開発工数も運用工数も増えます。

そう、この考慮したくない、そうおもいました。ですので思い切って割り切ることにしました。つまり、書き込みが発生するアクション内ではずっとマスターと接続させておく。こうすることでレプリ遅延しても同じアクション内でレプリ遅延は発生しないので考慮する必要はなくなります。(リダイレクト先のアクションでレプリ遅延がある可能性はありますが)

トラフィック特性上、更新系のアクションをマスターに向けても即座に詰まることはないので、これで良いと思っています。もし、トラフィックが激増して厳密に切り替えないと回らない…という状況になったら対策するとして、そうなったときはつまりサービスが拡大しているということなのでとても嬉しい状況ですね。

RAILS_ENV=testではシングルDBで

上述の通り、レプリ遅延を極力考慮しない割り切りなので、テスト実行においてレプリ遅延が発生するケースをあぶり出すような考慮はしません。ですのでCI環境やローカル環境ではシングルDBなのでレプリケーション設定もしてません。

マスター・リードレプリカとの接続状況をログに記録する

開発時に便利なので、ActiveRecordのクエリログに readonly or writable どちらに接続したかを記録するようにしました。ログの拡張には cookpad/arproxy を使いました。とても便利で感謝しかないです。

設定

# config/initializers/arproxy.rb

if Rails.env.development? || Rails.env.test?
  require 'switch_point_logger_enhancement'

  Arproxy.configure do |config|
    config.adapter = 'mysql2'
    config.use SwitchPointLoggerEnhancement
  end
  Arproxy.enable!
end

# lib/switch_point_logger_enhancement.rb

class SwitchPointLoggerEnhancement < Arproxy::Base
  def execute(sql, name = nil)
    proxy = SwitchPoint::ProxyRepository.checkout(:raksul)
    mode = proxy.mode
    name = "#{name} [#{mode}]"
    super(sql, name)
  end
end

 

ログサンプル

SCHEMA [readonly] (0.8ms)  SHOW FULL FIELDS FROM `tickets`
Ticket Load [readonly] (0.3ms)  SELECT `tickets`.* FROM `tickets` WHERE `tickets`.`staff_id` IN (100, 201, 12, 13, 71, 10)
Staff Load [writable] (0.3ms)  SELECT  `staffs`.* FROM `staffs` WHERE `staffs`.`id` = 2 ORDER BY `staffs`.`id` ASC LIMIT 1
Role Load [writable] (0.4ms)  SELECT `roles`.* FROM `roles` INNER JOIN `abilities` ON `roles`.`id` = `abilities`.`role_id` WHERE `abilities`.`staff_id` = 2

[readonly] [writable] の箇所です。

まとめ

運用中のRailsプロジェクトにSwitchPointを導入し複数DB化しました。

マスター接続デフォルト、リードレプリカ接続をオプショナルとすることで、既存コードの改修を最小に押さえて導入の敷居を下げつつ、リードレプリカを参照させるときはコントローラのアクション単位で制御するようにしました。

また、レプリ遅延の考慮は極力意識しなくて済むよう、マスター、リードレプリカの接続を混ぜるアクションを実装しない割り切りをしました。

これらにより、複数DB化した後も、素のRails(シングルDB運用)と同じレベルの開発スピード感を維持することができました。

実際、本番導入からしばらく立ちますが問題なく運用できており、また開発もこれまでどおりのスピード感で進めれています。

ラクスルではエンジニアを積極採用しています

いろいろ詳しく書きましたが、複数DB化にあたっての検討は私一人で行ったわけではなく、自社のサービス傾向や開発運用スタイル似合うかどうかを、周りにいるRailsに詳しいエンジニアにも相談しながら、進めていきました。1人で決めるより話し合って決めるラクスルのスタイルはとてもやりやすく感じています。

そういうわけでして、ラクスルでは私達と開発指針を議論しながら開発したいエンジニアを絶賛募集しています。是非一度オフィスに遊びにきてください!

mini specが流行っている??うちもいつかやろう

こんにちは。
Raksul Platform Projectの水島です。

先日ふとProduct Manager(以下、PM)の平光さんから、「これって水島さんの昔の記事のことですよね?」と声をかけられました。

なになに??おお〜、私が前職のtechブログに書いたmini specに関する記事がカウルさんのブログで紹介されているではないですか!

スタートアップの現場で役立つ開発要件のまとめ方

涙ぐましい。魚拓から復元してくれたのかな。。。感謝。

実は、このときのブログの中で、「mini spec」でググると、外車のMINIのスペック情報が出てきちゃうし社内用語だよ、と書いていたのですが、今はちゃんとQiitaの記事がトップで引っかかるではないですか!

新機能をつくる前に整理しておきたい10のこと

しかもクラウドワークスさんも一部ご活用とのこと!そして、mid specなるものが。。。参考になります!
スタートアップ界隈でこういったノウハウがシェアされ、活用されていることに感激してしまい、ついついブログで書きたくなってしまっていました。

ラクスルでも当然mini specとかmid spec書いているんだよね?

。。。
いや、今は決まったフォーマットで書いていないです。。。

なんか書かなくても各スクラムのPMがストーリー分解できていて開発は一定回っていた状況なので今はいいかなと(本当はメンバー自身でストーリー分解するのが普通かもですが、ラクスルではPMが結構やる)。エンジニアからすると背景が見えないよ問題は時々起こりますが明確に導入するに至っていません。

あと私がメインでやっているRaksul Platform Projectは、相手にしているシステムと刷新の規模が大きくて、miniもmidも収まらない。。。 まさにlarge spec。決まったフォーマットはなくつらつらと方針とか計画とか意思決定したことなど、必要なドキュメントをチームで書いています。

プロジェクトの特徴的にも手を動かしたほうが見えてくる技術負債も多いような状況なので、ハイレベルなロードマップ、アーキテクチャーとデザインをエピック的に、Trelloにざっくりとcardを書いてとにかくガシガシ進めるスタイルをこのプロジェクトでは採用しています。後から漏れているタスクが多々出てくるので都度cardを追加していきsprint計画どころではないこともあります。。。泣。

このプロジェクトが落ち着いてきて中小規模な案件が増えてきたら、またmini specの運用をちょっとづつ考えてみたいと思っていますが、PMがmini specやmid specを書いてエンジニアに伝えて、というよりは、多少非効率でもエンジニア自身で大枠の仕様を決めたり、直接ステークホルダーに絡むともっと開発って楽しくなるのかなって最近思っています。

最近ベトナムでのオフショア開発も少しずつ開始していますので、言語の壁があったりリモートの開発部隊と協業するシーンで背景や仕様を伝える時には良さそうです。元々、mini specは、日本とサンフランシスコのエンジニア間で企画や仕様を共有するために生まれたものですから。

Raksul Platform Project の進捗

先日、会員登録、ログイン周りのUI刷新、内部的な認証認可のAPIの刷新をリリースしました。

見た目のデザインも変えていますし、今までメールの通達確認をしていなかったのでカスタマーサポートの観点でも問題があった部分を改善しました。
メールの通達確認を必須にすると会員登録CVRが落ちるんじゃないかという懸念がありましたが、計測してみるとむしろ良くなる兆しがあるくらいです。本当にやってよかった。

これで若干中途半端感があったraksul-authという内部APIのアプリをやっつけることができそうです。

また、平光さんリードでマイページ(ログイン後の注文などの確認機能)の刷新もリリースされました。

今までメニューが分かりにくかったり、ページング処理がない画面などが一部あり、エンジニアやカスタマーリレーション部のメンバーからも改善したいという声が大きかった機能です。
印刷ECは物販のECと比べて注文のステータスやお客様にしていただくアクションなどが複雑なので、マイページはとても重要な機能です。そのマイページの負を技術的にもユーザー体験的にも改善することができました。まだ、古いページも一部残っていますが。。。今後の機能拡張と併せて刷新していけそうです。

並行して、三瓶さんの活躍により決済のサービスが着々と仕上がってきており、より法人の方の決済ニーズを満たすことができる機能に刷新されていく予定です。

ガシガシ行きましょう。

新機能はrubyとgolangで開発する潮流

社内の潮流として、Raksul Platform ProjectでRuby on Railsのアプリケーション基盤が揃ってきたので、中規模以上の新機能については可能な限りRuby on Rails側のアプリで開発することを選択するようになりました。ここ半年で大きく変わってきた感触があります。

早いもので印刷サービスではそろそろ年賀状・喪中はがきの販売がスタートします。今年は新機能を乗せて販売開始をしようと準備をしていますが、新しいrailsアプリケーションの上で開発しています。

一部のタスクはとある事情でgolangで開発し、非同期の処理にはAWSのS3トリガーのSQSを組み合わせて実現したりと、なかなか楽しい感じのアーキテクチャーになってきました。
社内にもgolangの入門書が雑多に置かれています。ビジネス的にもエンジニアにとってもお客様にとっても今年のラクスルの年賀状は楽しみです。

詳細は追ってどなたかが書いてくれると信じて。。。

ラクスルではエンジニアを積極採用しています

赤裸々に書きましたが、こんな感じの私達と一緒に開発を楽しんでいただけるエンジニアをラクスルでは募集しています。是非一度オフィスに遊びにきてください!

We participated RubyKaigi 2018 as sponsor!

(日) こんにちは、エンジニアのゴンです。

先日、RubyKaigi 2018にSticker Sponsorとして参加します でお知らせした通り、今回はエンジニア合計5名が仙台で開催されたRubyKaigi 2018に参加しました。

RubyKaigiはRubyをテーマにした国内最大級のイベントで、Rubyのエンジニア同士がソフトウェア開発の知識を共有し合い、Ruby未来を議論するOSSコミュニティを拡大する場でもあります。Rubyはラクスルを支える中心技術です。ラクスルは今後もRubyを積極的に活用していきたいと考えており、このような機会を通じて少しでもRubyの発展に貢献していきます。

(EN) Hi, I’m Yiwen, a RakSul engineer.

Shortly before, we announced our sponsorship in RubyKaigi 2018にSticker Sponsorとして参加します. This year, I’ve joined the conference along with four other RakSul engineers.

RubyKaigi is one of the biggest conferences focused on Ruby programming language. It opens an opportunity for Ruby developers to share knowledge of building software, as well as growing an active OSS(open source software) community to discuss future of Ruby. Ruby is Raksul’s core technology, we hope we can make our contribution to Ruby community through sponsoring RubyKaigi.

今回のノベルティー

(日) スポンサーとしてのステッカー以外に、独自の温泉タオルも用意しました。受け取った方はぜひ温泉で使ってください!

(EN) Besides being sticker sponsor, we also designed our own Onsen towels. If you got one, don’t forget to use it when going for Onsen!

参加したエンジニアの感想——その1

※ Japanese version only

こんにちは、エンジニアの三瓶です。最近はラクスルの基盤となるシステムの開発をしています。
ラクスルに入社してまだ3ヶ月も経っていない新参者ですが、今回のRubyKaigiに参加させていただきました。自分は今回が初めてのRubyKaigiです。

興味深かったセッション

今回、個人的に興味深く感じたのは、Ruby製フレームワークの Hanami に関するセッションでした。

Architecture of hanami applications

というのも、ラクスルではDDDを取り入れた開発をしており、ソフトウェアの設計に関して考えたり議論することがこれまでよりもずっと多くなっていたからです。

HanamiはDDDの影響を受けていることに発表の中で気づき、またそれがフレームワークとして目に見える形で現れていることもわかりました。

Railsと表面上似ている部分もありますが、設計思想はかなり異なるように思います。
これまでRailsに触れる時間が長かったのですが、Hanamiの設計思想を学ぶことで、ソフトウェアの設計に関しても新しい知見が得られそうだなと感じたことが、興味深く感じた理由でした。

Rubyist達との交流

セッションだけでもお腹いっぱいですが、RubyKaigiは様々な人と交流する機会が多くあり、そういった点でも楽しむことができました。
また、各スポンサー企業の提供するノベルティや催しも充実していて、中には10000円のAmazonギフト券が当たるガチャポンを無料で提供している企業さんまでありました。

写真は、奇跡的に10000円のギフト券を引き当てた私の写真です。

 

 

 

参加したエンジニアの感想——その2

所感

こんにちわ、エンジニアの藤田です。私は、去年の広島に続いて2回目のRubyKaigiでした。初参加時もカンファレンスの規模の大きさとレベルの高いトークに圧倒されましたが、今年のRubyKaigiはより大規模になっていたと感じました。特に、参加者数やスポンサーの数、アフターパーティーの充実度は目に見えて伸びており、年々RubyKaigiの認知度や企業への影響力が上がっているのだなと実感しました。

気になったトーク

興味深いトークは非常に多かったのですが、個人的に衝撃的だったのは@k0kubunさんの「The Method JIT Compiler for Ruby 2.6」でした。発表はRuby2.6で導入予定のJITに関するもので、内容自体の面白さもさることながら、k0kubunさんの恐ろしいほどの早口と生き生きとした表情から、真のエンジニアとはいかなるものかを体現していたように感じました。

牛タンとOculus Go

仙台といえば牛タンですが、1日目のOfficial Partyが終わった後、弊社の有志でホテル近くの牛タン屋に飲みにいきました。最近、Oculus Goを買ったばかりだったので美味しい牛タンを食べつつOculus Goを初めて体験する同僚を見てニヤニヤしていました。(VRを体験している人を外から見るのって楽しいですよね)

Impression of the Conference From Our Engineers——Part 3

※ 以下英語のみ

Finally, it’s me, Yiwen. I’m a new graduate engineer, as well as one of the international employees in Raksul. While I was in college, I had one year exchange experience in Japan, and that’s when I met Ruby. I soon became obsessed with Ruby and decided to become a Ruby developer. Now I’m developing a new design service.

My Favorite Session

I’m overwhelmed with tons of new frameworks and topics from RubyKaigi! My favorite topic is Ruby code from the stratosphere – SIAF, Sonic Pi, Petal. It introduces a concept called live programming (a performance which people improvise music by typing programming instructions and let the program to create sounds). To me it’s a perfect combination of technology and art!

Communication with Other Rubyists

The other thing I enjoyed was building network with Ruby developers all around the world! After the conference ended, we moved to a park in the city center and kept talking about new technologies, Rails community, and career path as an engineer. The thing we had in common is that we all use Ruby to make great services!

Conclusion

We had so much fun in RubyKaigi this year! See you next year in Fukuoka!

お知らせ

ラクスルではRubyistを募集しています。ラクスルにご興味を持たれている方、カジュアルな形でぜひお話しましょう

PMに必要なスキルとは?新卒が1年を通して感じた4つの要素

こんにちは!ラクスルでプロダクトマネージャー(以下、PM)をしています平光です。
17卒の新卒として入社し、1年とちょっとが経過しました。
今日はこれまでの振り返りと学びを紹介しようと思います。

ラクスルにおけるPMの役割とは

ラクスルでは、要件定義からストーリー分解、スプリント / 長期の開発計画、受け入れテスト、サービスのリリースまでをPMが担います。
チームによっては、システムの設計にPMが入って議論したり、ワイヤーやデザインをPMが行うこともあります。開発チームによって求められる役割が異なりますが、チームに足りない部分を自分がカバーするかもしくはリソースを調達することで、サービスのリリースまで進めます。

役割が異なることによって幅広い業務に関われることはPMをやっていて楽しいですね。

課題設定が甘く優先順位が付けられない

入社してまず関わったのがラクスルのカスタマーサポート(以下、CS)チームが使う管理画面の機能拡張、再構築です。とはいえ、入社前にPMとして働いた経験があるわけもなく様々なことに戸惑いました。

例えば、

「機能一覧を書き出したり、実際に使う人にヒアリングして課題を書き出したりするもののどこから手をつけてよいかわからず優先順位が決められない」
「今のシステムがどのように作られているかわからず工数の見積もりができない」

大きなシステムだったので課題を把握した後、エンジニアと会話しながらスコープを小さく区切って開発していくのがよかったなと今になって思います。

シニアPMのもとで3ヶ月修行

約半年CSチームのPMをした後、ジョブローテーションの一環で発注基盤や物流などに関わるチームに異動しました。

シニアPMのもとペアワークをしながら、設計、ストーリーの作り方、プロジェクト管理、優先順位決め、エンジニアとのコミュニケーションなどについて学びました。
※ラクスルでは、ペアプログラミングだけでなく、場合によってはデザイナーやPMがペアワークをすることもあります。

この3ヶ月間で特に、ストーリーの作り方、分解の仕方について勉強になりました。

ストーリーは基本的なユースケースを満たせる幹となる部分から順に作り、その後エッジケースにあたる枝葉の部分のストーリーを書いていきます。

そうするとおのずとMVPから順にプロダクトを作っていくことが可能になります。

簡単な例ですがブログ投稿機能を題材に書いてみました。
ブログ投稿なので、ブログを投稿できるまでの必要な機能は幹となる部分ですね。
公開設定機能などは、ブログを投稿できるという要件に対してマストではなく、枝葉となる機能なので運用していく中で必要となったら開発。みたいな判断ができるかもしれません。
要件を考えれば考えるほど肥大化していきますが、開発リソースは限られているので本当に重要な機能かを見極めるのは大切だなというのを感じました。

また、ラクスルでは多くのチームで As / Given / When / Then… のGherkin記法を用いてストーリーを書きます。
ストーリーの書き方については過去の記事でも紹介しているので気になる方はそちらを見ていただければと思いますが、僕が実践している中で最も重要に感じたのはテスト可能な単位に小さくストーリーを分解することです。
そうすることで、工数の見積もりもしやすくなりますし、PMの受け入れテストもやりやすいです。
結果的に、見積もりが正確になっていると想定スケジュール通りに開発を進められるはずです。

プロダクト開発部のPMへ

その後、メインPMとしてスピードチェック入稿の商品拡張やマイページのリニューアルなどのプロジェクトに関わります。

デザイナーやフロントエンドエンジニアとプロダクトのデザインについて密にコミュニケーションを取り始めたのはこのタイミングが初めてでした。
また、属人的なテストを脱してテストを自動化するなどの守りの施策も重要だと認識したのもこのタイミングが初めてでした。
一歩引いた立場で全体を俯瞰し守りの開発も適度にプランニングできることも重要だと感じました。

1年を通して感じたPMに必要な要素

入社時は「PMの役割ってなんだろう」「PMのスキルセットってなんだろう」と思っていましたが、この1年を通して少しずつそれが明らかになってきた気がします。

  • 現状と課題を把握するためのドメイン知識
  • プロジェクトを進めるコミュニケーション
  • 意思 / こだわりを持って意思決定する
  • プログラミング、デザインへの理解

上記4つ、僕がPMに必要だと思った要素です。
一つずつ簡単に解説すると。

現状と課題を把握するためのドメイン知識

ドメイン知識が薄いと結果的に課題設定が甘くなり、プロダクトをリリースしてもエンドユーザーに使ってもらえなかったり、評価がいまいちだったりすると思います。

印刷 / データチェックの知識ももちろんですが、エンドユーザーがどうラクスルを使っていて何を課題に感じているのか、オペレーターが管理画面を使っていて何が使いづらいのかということを把握するのが大事だと思います。

プロジェクトを進めるコミュニケーション

プロジェクトを進める上で、エンジニア、デザイナー、顧客対応をするCSチーム、印刷委託先などなど多くの人が関わります。密にコミュニケーションをとらないとヌケモレが発生したりリリース直前でどんでん返しが発生してしまいます。特にエンジニアやデザイナーなどのプロダクト開発に直接関わる人たちに対しては、なぜそれが必要か?その課題に対して考えている解決方法が最適か?といったプロジェクトの意義について共通認識を持っておくことが特に重要だなと感じます。

悪い例だなと思うのは、JIRAなどのチケットに書いてある要件とかだけのテキスト中心のコミュニケーションしてしまうこと。
逆にいい例だなと思うのは、実際のUIや処理の流れの図を示したものをボードに貼るなどして、「ここに〇〇な機能が必要」「ここは〇〇の条件分岐で出し分ける」などを話すこと。そうすることで全体のゴールイメージの共通認識が持てるので、考慮漏れも発生しづらくなると思います。

意思 / こだわりを持って意思決定する

「この機能は初回のリリース時点では外そう」といったことが往々にしてあります。
開発工数の兼ね合いやリリース日との兼ね合い、または関係各所との調整で当初のスコープから変更をしたり、リリース日を調整したりすることがPMにはあると思います。そうした意思決定や判断ができてプロジェクトをとにかく前に進めていく力が必要です。

また、プロダクトや機能に対するこだわりを持てるともっと自分自身楽しくなるよ。とシニアPMからフィードバックをもらいました。

プログラミング、デザインへの理解

PMはエンジニアやデザイナー、ビジネスの人とのハブになっていることが多いです。
エンジニアとコミュニケーションをする上でもプログラミングへの理解があると「こういうやり方はどうか?」「こっちのほうが工数は少なくできそう?」といった話ができると思います。また、開発工数の見積もりもより正確にできるかと思います。デザイナーとのやり取りも同様です。

とはいえ、チームや会社によるのかなとは思います。
「PMにプログラミングスキルは必要か」というテーマの記事や勉強会を耳にしますが、やはり知見はあったほうがいいなと僕は感じます。

ラクスルのプロダクト開発のおもしろさ

プロダクトの企画、実際に形にしていく開発、リリースまでの全てに第一線で関われるところはとても魅力的です。

オペレーションの設計を考えて、それをシステムに落としていくところだったり、部署やチームが変わるに連れ印刷 / データチェック / 発注基盤など必要なドメイン知識が変わっていくところもラクスルのおもしろさだなと思っています。

今後は、より自分なりのプロダクトへのこだわりや強い意思を持ってリリースしていきたいと思っています。

デザイン指針の必要性

こんにちは、ラクスルでUXデザイナーをやっていますガーワルロビンです。6月にオランダのアムステルダムで開催されたUXデザインのカンファレンス2つに参加してきました。UX戦略とUXデザインに特化した「UX STRAT Europe 2018」が6月11日・12日に開催され、またフロントエンドやテックの話も少し入った「CSS DAY 2018 UX Special」が6月14日に開催されました。

左:UX Strat Europe 2018の会場;右:CSS Day 2018の会場

ラクスルは2012年からネット印刷のサービスを提供し続けてしました。この6年間の間でサービスの形は変わり、ユーザーとのタッチポイントも変わってきました。変わり続けるウェブサービスを開発するにはプロダクトの形をリードする指針が必要だと思われます。ラクスルにそう言った指針がなかったため、ユーザー体験の一貫性がなくなってきました。ユーザーにより良い体験を提供するためには、どのようにプロダクトを作ればいのか、どのような組織でどのような開発を進めれば良いのか。いままでラクスルで進めてきた方法が正しいのか?もしくは別のアプローチがあるのか?その答えを探すため、カンファレンスに参加しました。

その答えになりうる勉強になった事項のひとつは、デザインプリンシプル(以下デザイン指針)でした。このブログでは主にデザイン指針とは何か、なぜ会社に必要かと最後に良いデザイン指針を作るためのコツを紹介します。では早速本題に入って行きましょう。

デザイン指針とは

CSS DAYの登壇者の一人で「Design Systems」の著者 Alla Kholmatova はデザイン指針を次のように説明しています。

デザイン指針は、特定の製品やチームにとって良いデザインが何を意味するかという共通の基準です。

ウェブ上で出てくるデザイン指針には様々な定義があるかもしれませんが、私にとってはこれが単純でストレートです。[参考までにInteraction Design foundation

デザイン指針の必要性がどこにあるのか

デザイン指針は、プロダクト開発において組織の基準を一方向に定めるために重要です。

Brio toys

Brioが色々なおもちゃを作っている中で、一目瞭然でBrioのおもちゃであることがわかります。

複数のプロダクト間の一貫性を保つ

デザイン指針があることによって、同じサービスやブランドに含まれるプロダクトにユーザーが接するときに迷わずに動作をすることができます。 ユーザーがプロダクト間で一貫性のある経験を持ち、同じ機能が違うプロダクトで複製することができれば、タスクをスムーズに進めることができます。 この一貫性は、Atlassianの幅広い製品で見られます。 Atlassianは3つのデザイン指針を定義し、プロダクトの必要に応じてそれぞれの度合いを微調整して行きます。

アトラシアンが定義している3つのデザイン指針

アトラシアンが定義している3つのデザイン指針

時間依存性を減らす・長期間で一貫性を保つ

事業会社では同じサービスを何年も、もしくは何十年も市場に出すことがあります。 ビジネス制約の変化やチームの変化によってプロダクトに対する良いデザインの定義も変わることがあり、長期間経つとサービスはユーザーにとって一貫性のない体験になりがちです。 デザイン指針を中心にプロダクト開発することによって長期的にものを同じ軸で評価することができ、組織やビジネス制約に依存性を減らすこともでき、一貫性の高い体験を提供することができます。

共通言語化で効率化

デザイン指針を明確に定義することで、組織のメンバーがプロダクトの開発や評価に関して同じ言語でコミュニケーションを行い、効率的に話を進めることができます。 開発ペースが早いウェブサービスにおいては短時間で精度の高いコミュニケーションを取り、デザイン判断を行えることがキモになると思います。

良いデザイン指針を定義するには

良いデザイン指針を定義するにはAlla Kholmatova民の「Design Systems」に戻って、話をしたいと思います。良いデザイン指針は以下の4つのパラメータで測ることができるそうです。
1. 本質的:実際の具体的な施策で説明をすることができること
2. 反意語が成り立つ:別の会社がそれの反意語でデザイン指針を定義することができること
3. 行動に起こせる:プロダクトの評価軸になること
4. 記憶に残る:シンプルで覚えやすい、いつでも思い出せること

またデザインプロセスをご存知の方はイテレーションを回す重要性がわかると思います。デザイン指針も同じように定義したもをでプロダクトを作ってデザイン指針のFine-tuningをする必要があります。これによってデザイン指針が会社のミッションや顧客価値からズレていないかを確認することができ、より洗練されたデザイン指針・プロダクト・ユーザー体験を作ることができます。

良いデザイン指針を定義するためのTIPSをいくつかあげます!
・会社のミッションから始める
・横断的なテーマを見つけ出す
・誰に向けてのデザイン指針なのかを明確にする
・仮説検証をおこなう  

サマリー

今回はデザイン指針について書かせていただきました。デザイン指針とは何か、それがあることによって会社へのメリットはあるのか、に加えて良いデザイン指針を作るためのTipsをいくつかあげてみました。

この二つのカンファレンスに参加することによって、確かにデザイン指針があることによって長期的により良い・洗練されたUXを設計することができると感じました。ラクスルでは現在以下のようデザイン指針を定義しています。私たちもデザイン指針の運用が初期段階にいるので、これからイテレーションを回して、改善する必要を感じています。
・シンプル:ユーザーがタスクを実行するうえで不要な機能やビジュアルエレメントが含まれていないか?
・明瞭:ユーザーがタスクを実行するうえで重要なアクション項目はひとつに絞られているか?
・一貫性:同じ機能で異なるビジュアルや性能をユーザーに提供し、混乱を招いていないか?
・速い:ユーザーは最短のスピードで必要な情報にアクセスできているか?

ラクスルでは、このデザイン指針を決めるためのワークショップをデザイナーやプロダクトマネージャーを交えて行う予定です!

私たちはユーザーにより良い体験を提供していくことに努めています!
良い体験づくりで世界をもっとよくしてきませんか?
ラクスルでは様々な職種の方々を募集しています。ラクスルの採用ベージへ
ラクスルについてもっと知りたい場合はこちらをご覧ください。

RubyKaigi 2018にSticker Sponsorとして参加します

こんにちは。エンジニアの三瓶です。

ラクスルは、2018/05/31 ~ 2018/06/02に仙台国際センターで開催される RubyKaigi 2018 にSticker Sponsorとして参加します。

RubyKaigiは、プログラミング言語Rubyに関する国内最大級のイベントです。
Rubyはラクスルを支える中心技術であり、今後も積極的に活用していきたいと考えているため、このような機会を通じて少しでもRubyの発展に貢献していきます。

今回のRubyKaigiではSticker Sponsorとして、毎年配られているRubyKaigiのステッカーをラクスルにてスポンサリング・納品させていただきました。

また、ラクスル自身のステッカーや便利でかわいいノベルティもご用意していますので、是非ノベルティ置き場にお立ち寄りください。