RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのエンジニアブログ

エンジニアリングマネジメント:開発の文化

株式会社ラクスでエンジニアリングマネージャをしているmzwkunです。

先月開催されたDevelopers Summit 2019にて、AWSの方が『イノベーションを支えるアマゾン文化』というテーマを発表されていたので、普段行っている自分たちの開発スタイルと比較して、特に気になったところをピックアップしていきます。

多彩で使いやすいサービスを提供されているAWSさんと比較して学べればと思っています。

AWSイノベーションの文化

  • 顧客に徹底的にこだわる、顧客を起点に行動する
  • 長期的視点での継続した投資
  • ビジョンにはこだわるが、詳細なことは柔軟に対応
  • もし創造的でありたいなら失敗を恐れない

ラクスにはリーダーシッププリンシプルがあり、少し表現は違いますが以下と合致しそうだと感じました。

「やるべきことを実行する」「小さく試して大きく育てる」「誠意をもって人と接する」「失敗を許容する」

自分のやりたい事ではなく、顧客視点や失敗を恐れないでチャレンジする点はイノベーションの起点ですね。

AWSイノベーションのための組織づくり

  • 新サービス開発を行う際にまずはプレスリリースとFAQを作る
  • FAQは顧客とステークホルダー(社内関係者)の両面を含める
  • 会議でプレゼンツールはあまり使わず見た目に委ねないようにする(見栄えで騙されないように)
  • 6pagerと呼ばれるレポートを作り事前に読んでおく(ナラティブ【物語】とも呼ばれている)

目的や効果を定めるために真っ先にプレスリリースを作るのは興味深い行動ですね。

私達の開発では「要求仕様書」というドキュメントを企画と開発、関連部署で作成して意識を合わせるようにしています。 そこには要求概要や機能要求など定めるべき当然なものから、保守・品質・性能・運用・サポートといったサービス全体に必要と思われるものが記載されています。 プレスリリースは作れていませんが、ステークホルダーの視点は全て集約できるようにし、レビューによって多様な立場からの意見を受け入れるようにしています。

AWSアーキテクチャ

  • 単一目的のサービス
  • HTTPSAPIのみによる通信
  • お互いのサービスはブラックボックス
  • DevOpsを推進(テストを重視、自動化を重視)

マイクロサービスを前提にテストや自動化の重視と奇をてらうこと無く基本に忠実でした。 ラクスでもDevOpsは外部に任せず内製で力をつけながら進めています。

AWSのカルチャー

  • 5 whys (いわゆる、なぜなぜ)
  • ドアデスクがある 創業時にドア用の板を簡素な机にしていた ※倹約を忘れないように!
  • スピード 過剰な分析、過剰な議論よりもプロトタイプを作ってみる
  • ベストを尽くす 高い目標、メンタリング、ピアフィードバック

QCD、ロジカル、インタラクションというキーワードになりそうです。 ロジカルはラクスでも古くからの重要な文化であり、インタラクションも最近重要視されていて、1on1ミーティングやコーチングというワードが飛び交っています。 そこからどのような行動に移しているかは今後ご紹介したいと思います。

AWSの組織

  • 2-Pizza Teams 必ず目が行き届くように
  • QA、障害対応、運用はすべて自チーム内でやる
  • 早く経験し、繰り返す
  • レビュー待ち状態は厳禁!

やはり10人以下のチーム構成による、きめ細やかなコミュニケーションを土台としたチーム開発が重要そうです。 ラクスでもメンバーを増やすだけではなく、リーダーやマネージャも積極的に育成や採用をして不自然な構成にならないよう努めています。 自チーム内でやるというのも、全てを内製で進めているラクスと似ています。 レビュー待ち厳禁は少し耳の痛い言葉ですが、リーダーの皆さんが頑張って効率性を守ってくれています。

Every day is still Day One.

  • 毎日が常に「Day One」である
  • 最初の一歩を踏み出す日
  • 新たな挑戦を心待ちにする日
  • そして今日が、皆様にとっての「Day One」

素晴らしい考え方ですね。素直に参考としたいです。

いろいろと見ていきましたが、共通となりそうな点も多く、自分たちのやっていることにさらに自信が持てそうです。

JJUG CCC 2018 Fall 【参加レポート】

f:id:sts-250rr:20190317152347p:plain

はじめに

こんにちは。

年末にJJUG CCC 2018 Fallに参加してきましたので、少し期間が空いてしまいましたが、聴講したセッションについて投稿します。

当日のタイムテーブル、資料は下記をご覧ください。

https://docs.google.com/spreadsheets/d/1cyNPjk8doq26FgjhLVwA0Pw2grGFwxqo4yVXqJgQCTE/edit#gid=413114967

qiita.com

参加セッション

  1. IBM CloudとKubernetesでSpring Bootのマイクロサービスを簡単に!

  2. エムスリーでのKotlinへの取り組み

  3. Java を活用したマイクロサービスのための Kubernetes 活用

セッション感想

IBM CloudとKubernetesでSpring Bootのマイクロサービスを簡単に!

IBMクラウド上にKubernetesクラスタを作成して、DBの構築、事前にDockerイメージとして作っておいたSpring BootのJavaアプリケーションをデプロイしてサービスを構築していくセッションとなっていました。 先日からDocker周りに興味が湧いているところなので、次はKubernetesに手を出すいいきっかけになりそう。

エムスリーでのKotlinへの取り組み

f:id:sts-250rr:20190321221448j:plain

運用中のJavaアプリケーションをKotlinに移行する話。
移行の方法としては3通りほど考えられていましたが、今回は「全部まとめて書き換える」方法を取られていました。
コンバート中は完全に機能開発を止めて、移行をすることに集中、余計なことはしない、短期間に完了する。
移行作業のノウハウを学ぶことができ、システムをAからBに移行するぞとなった時の参考になりそうです。

Java を活用したマイクロサービスのための Kubernetes 活用

f:id:sts-250rr:20190321221522p:plain

かなり内容の濃いセッションになっていて、k8sにまだ触れていない私は少々パンク気味でしたが、今後自身でK8sを触る時の参考になるTips紹介が多かったです。

Docker関連

  • Dockerイメージの取得時、いつのバージョンかわからなくなるのでlatestは使わないこと!
  • 小さなサイズのイメージをつくるように!
  • DockerHubのイメージは安全か?
    • 信頼されてないイメージは脆弱性が含まれている可能性はある。
    • 本番利用するならセキュリティチェック・検証はしましょう。

k8s関連

  • 利用用途によって、向き不向きあるので何でもかんでもk8sでというのはやめましょう。
  • k8sは色々できるけど、全ての機能を使う必要はない!
  • 後々のメンテナンスのことも考えてシンプルな構成にしておくのがおすすめ。
  • k8sのバージョンアップには要注意!
    • 今まで動いていたyamlでは動かなくなる可能性がある。
    • 新しくクラスタを作成して、動くことがわかってからルーティングを変えて対処しましょう

Docker、k8sに関してはまだまだ初学者であるため、触り程度でしかわかっていない部分がありますが、今後触っていく際の有益な情報になりました。

何でもかんでもk8sでというのはやめましょう。
私もよく言われていて耳が痛いですが、手段ベースでものを選んではいけないの典型ですね。

終わりに

JJUGには昨年度から参加していますが、昨年よりも内容がわかるようになっている自分を感じることができました。
同じテーマで複数の発表があれば今のトレンドの技術はこれなのかな?といった業界の流れのようなものも少し感じられた点も昨年から参加していた成果かと思います。

若手にとって、はじめての勉強会やカンファレンスへの参加は足が重い人が多いかもしれませんが、大きめのカンファレンスは参加のハードルも低いので、1ヶ月後に入社する新メンバーにもオススメしてあげたいです。

大阪開発ビアバッシュレポート ~3月「トラブル事例特集」~

こんにちは。新卒1年目エンジニアのbadaikiです。

はじめに

今回は、先日大阪オフィスで開催された3月ビアバッシュをご紹介いたします。
前回のビアバッシュの記事はこちらです。↓

tech-blog.rakus.co.jp

テーマ枠発表

今回のテーマは、「トラブル事例特集」。今年度に発生したトラブルを発表していただきました。
「今年度のトラブルは今年度のうちに」ということで、何が原因でどのように対処したのか、各チームに当時の心情も込めてお話していただきました。
共有したいところなのですが、ほとんどの内容が社外秘の内容のため以下は発表全体の総括になっております。

全部で5つのサービスで起きたトラブルを発表していただきました。
なかには「リリース日と震災が重なったことで出社できた社員が2名という状況下で発生したバグ対応」というものもあり、そういうこともあり得るのだと知りました。

トラブルを起こさないことが一番ではありますが、トラブルが起きてしまったときに如何に冷静かつ迅速に対応できるかが重要になると感じました。すぐには難しいですが、いずれは私もトラブルの対応ができる技術を身につけていきたいです。

これまで配属されてからほとんどのビアバッシュに参加してきましたが、いつものビアバッシュと比べて緊迫感があったような気がしました。

自由枠発表

テーマ枠のほかに自由枠発表もありました。
テーマ枠とは異なり、今自分が気になっていること、伝えたいことを題材に2名の発表者が登壇してくださいました。今回は2名とも新卒1年目の若手が発表していただき、最近つまったことや今年度を振り返った内容となっていました。

サービスの環境構築

チームに新しく参入するメンバーの環境構築や開発の準備を行った際に、苦戦した点を発表していただきました。
あと3か月ほどすれば新卒の後輩が私のチームにも配属されるため、私も他人事ではないなと考えながら聞いておりました。 手順書に記載されている通りに行うのではなく、なぜこのスクリプトを叩く必要があるのか、なぜこの作業が必要なのか、を考えながら作業をしていくべきだと感じました。

1年間で得た新たなCSSの知識

新卒1年目のメンバーが配属してからの期間で得たCSSの知識について発表していただきました。
この方は学生のときからCSSに興味があり使っていたそうなのですが、業務レベルにはまだ達していなかったことを痛感したそうです。

f:id:badaiki:20190318192633p:plain

私も学生のときに得た知識だけでは足りないと思う節がこの一年間だけで多くありました。今の知識だけで十分だと慢心せずに積極的に技術を吸収することの重要さを再認識いたしました。

f:id:badaiki:20190318192410p:plain

最後には彼の今後の成長意欲を感じました。

おわりに

普段はあまり聞くことができない各サービスのトラブルについて聞くことができました。直で聞くことにより、当時の緊迫感なども伝わり普段のビアバッシュとは一風変わったビアバッシュだったのではと感じました。
私自身はまだ大きなトラブルに見舞われたことはありませんが、発生時には慎重に対応していきます。

ラクスでは同じような問題を二度起こさないよう、開発全体で起きた問題やその対処法を共有しております。 過去の知見を活かし、障害を乗り越え、ラクスのサービスは進化していきます。

SchooでJavaScriptについて学習してみた

はじめに

はじめまして、新卒1年目のエンジニアのmrym_618です。

今回は、SchooでJavaScriptについて学習してみましたので、その感想を書いていきます。

目次

Schooとは

Schoo(スクー)とは、大人たちがずっと学び続ける生放送コミュニティであり、参加型の生放送授業と、4,600授業以上の動画教材で 「仕事に活きる」知識・スキル・考え方を学べるサービスです。

schoo.jp

  • 特徴
    • プログラミングやWebデザインなどのIT分野以外にも英語やビジネススキル、企画・マーケティングなど幅広い分野の授業がある
    • 生放送ならではの講師や生徒同士でのリアルタイムなコミュニケーションをとることができる
    • PCだけでなく、スマートフォン、アプリからも利用することができる

実際に学習してみた

今回は、業務でも使うことが多いJavaScriptについて改めて学習したいと思い、JavaScript入門を受講してみました。 また、ドットインストールでもJavaScriptについての学習を行い、Schooとの比較をしてみました。

schoo.jp

Schooとドットインストールの比較

  • Schoo

    • 講義ベースなので、基礎からわかりやすく学習できる
    • 講師の方が実際のエンジニアの方なので、現場ではどのように使われるかを話してくれる
  • ドットインストール

    • 一つ一つの項目を短時間で学習することができる
    • 知りたい項目をピンポイントに学習できる

新しいことなど基礎からしっかり学習したい場合は、Schooで学習した方が分かりやすいと感じました。逆に、ある程度知識があり、短時間でピンポイントに学習したい場合は、ドットインストールで学習する方がいいと感じました。なので、どのように学習したいかによって使い分けることが大切だと思いました。

まとめ

今回は、SchooでJavaScriptについて学習しました。Schooは、新しいことを基礎からしっかり学習するには分かりやすいと感じましたので、今後も様々な分野を学習するときに活用していきたいと思います。

【PostgreSQL】大量データの投入にgenerate_series()関数の使用をおススメする3つの理由

はじめに

こんにちは、新卒で入社して3年目のnorth_mkyです。
最近業務でSQLチューニングをする機会があったので、実行計画を読み解く記事を書こう!...と思いたったのですが、記事を書くにあたってサービスのデータベースを使うわけにはもちろんいかないので適度なサンプルデータベースを作成し、 大量のデータを投入する という準備作業を行う必要がでてきました。

今まで大量のデータを入れるという作業はあまりしたことがなかったため、備忘も込めて当初予定していた記事を書く前に大量データの投入について述べたいと思います。

PostgreSQLに大量データを投入する方法は大きくは2つ

色々探していると、大きくは下記2つが投入方法として出てきました。

  1. CSVファイルをインポートする方法
  2. generate_series()関数を使用する方法

1. はpostgresqlが用意しているCOPYコマンドを使用する方法です。公式のお墨付きです。

14.4. データベースへのデータ投入
データベースにデータを初期投入するために、大量のテーブル挿入操作を行う必要がままあります。 本節では、この作業を効率良く行うためのちょっとした提言を示します。
(中略)
単一コマンドですべての行をロードするために一連のINSERTコマンドではなく、COPYを使用してください。 COPYコマンドは行を大量にロードすることに最適化されています。

https://www.postgresql.jp/document/10/html/populate.html

ですが、公式の言葉を押し切って今回私は2. generate_series()関数を使用する方法をおすすめします。

generate_series()関数を使用する方法をおすすめする3つの理由

1. 大量データ投入処理までの準備はなし

両者の作業手順は以下になります。
投入方法1では大量データを生成する→生成したデータをインポートする、というデータ投入前にデータを用意する準備作業が発生しますが、投入方法2ではデータ生成→データインポートの両方の処理をSQL1文で行ってくれるため、投入するまでにかかる準備はありません。generate_series()関数は標準で入っているので拡張モジュールの読み込み等も不要です。

  1. CSVファイルをインポートする方法
    1. CSVファイルを生成するスクリプトを作る
    2. 作成したスクリプトを実行する
    3. COPYコマンドに適切な引数を与えて実行する
  2. generate_series()関数を使用する方法
    1. 大量データを生成するSQLを作る(generate_series()関数を使用)
    2. SQLを実行する

2. 学習コストがほとんどない

投入方法1のCSVファイル生成スクリプトは自分の好きなやり方で組めばいいのでそこまで時間はかかりませんが、鬼門はCOPYコマンドだと思います。COPYコマンドはおそらく大量データの投入か、既存テーブルの別テーブルへの複製に使うと思いますが、いざ使おうとすると色々お作法に馴染みがなく手間取ってしまいます。

COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]

ここでoptionは以下のいずれかです。
FORMAT format_name
OIDS [ boolean ]
FREEZE [ boolean ]
DELIMITER 'delimiter_character'
NULL 'null_string'
HEADER [ boolean ]
QUOTE 'quote_character'
ESCAPE 'escape_character'
FORCE_QUOTE { ( column_name [, ...] ) | * }
FORCE_NOT_NULL ( column_name [, ...] )
FORCE_NULL ( column_name [, ...] )
ENCODING 'encoding_name'

https://www.postgresql.jp/document/10/html/sql-copy.html

ファイルパスの指定1つにしてもwindowslinuxで異なるのはもちろんのこと、投入するカラム値に空白が入っている場合の扱いを指定したりなど、馴染みのない人間にとってはトライアンドエラーで時間がかかります(私は5-10分かかりました)。

一方投入方法2はいつもどおりSQLを作成するだけなので学習コストはほぼなしです。

3. 実行時間がCOPYコマンドと変わらない

これは実測して驚いたのですが、両者とも投入時間はほぼ変わらないという結果になりました。

公式のお墨付きのCOPYコマンドと同等の処理性能で、準備に時間がかからないというので私はこのgenerate_series()関数を使用する方法をおすすめします。

generate_series()関数を使用した大量データ投入方法とは

「顧客テーブルに1000万行のデータを入れる。名前は"ラクス太郎n"にする(n=1...10,000,000)」

上記を満たす大量データ生成SQLは以下になります。
1000万行が入った1GB超のファイルを用意する必要はありません。SQL1文で作成できます。

INSERT INTO customer (id,name) 
 SELECT 
     i, format('ラクス太郎%s', i)
 FROM
     generate_series(1,10000000) as i
;

SELECT部分だけを打つと下記が返ってきます。

    ?column?    |        ?column?      
----------------+------------------------
              1 |       ラクス太郎1
              2 |       ラクス太郎2
              ...
       10000000 |    ラクス太郎10000000

連番を生成し、集合として返すgenerate_series()関数を応用すると、このようにその場でテーブルを作るようなことができ、大量データを投入することができます。他にも上述のformat()関数のようにrandom()関数などと組み合わせるといい感じの大量データを手軽に作成することができます。

検証 : COPYコマンド VS generate_series()関数

あるテーブルに1000万行を投入する処理の経過時間を計測しました。

環境

サンプルデータベース

PostgreSQLTutorial.com のサンプルデータベースを使用しました。
チューニングの記事を書く目的だったため、ある程度外部キー制約があったりカラム数があったりするデータベースはないかな、と探していたらすぐにこのデータベースが見つかりました。

結果

両者ともほぼ同じ結果になりました。

  1. COPYコマンド
dvdrental=# COPY customer (store_id,first_name,last_name,email,address_id,activebool,create_date,last_update,active) FROM '/Users/north_mky/customer.csv' ( delimiter ',', format csv, header true );
COPY 10000000
Time: 556051.126 ms (09:16.051)
  1. generate_series()関数
dvdrental=# INSERT INTO customer (store_id,first_name,last_name,email,address_id,activebool,create_date,last_update,active)  
dvdrental-# SELECT 
dvdrental-#     2,
dvdrental-#     'Austin',
dvdrental-#     format('Cintron%s', i),
dvdrental-#     format('austin.cintron%s@sakilacustomer.org', i),
dvdrental-#     605,
dvdrental-#     't',
dvdrental-#     '2006-02-14',
dvdrental-#     '2013-05-26 14:49:45.738',
dvdrental-#     1
dvdrental-# FROM
dvdrental-#     generate_series(1,10000000) as i
dvdrental-# ;
INSERT 0 10000000
Time: 558479.994 ms (09:18.480)

おわりに

generate_series()関数は大量データの投入に対して、楽に導入できて楽に使える関数です。
テスト時に大量データが必要になった際の手助けになれば幸いです。

RAKUS Meetup Tokyo #2 フロントエンドNight : イベントレポート

f:id:moomoo-ya:20190308181401p:plain
RAKUS Meetup のロゴ

@moomooya こと 勉強会最速オジサン を目指している鈴木です。 先日弊社にて RAKUS Meetup Tokyo #2 フロントエンドNight と称したイベントを開催しましたので、そちらのイベントレポートを投稿します。

いつもはイベント閉幕後3秒以内にレポートを公開しているのですが、今回は1,688,400秒ほど経過してしまいましたorz

  • 当日の様子
  • 発表の紹介
    • Vue.js の新規プロダクトで楽して UI を提供しようと思ったらそこまで楽じゃなかった話
      • 話の経緯と発端
      • 選択の成否
      • 鈴木の感想
    • 既存 Web アプリケーションへの React.js 適用
      • 話の経緯と発端
      • React 導入にあたってやったこと
      • 既存実装との共存と、その後の課題
      • 鈴木の感想
    • Vue.js を初めてプロダクトに導入して直面した課題と得られた幸せ
      • プロダクトに Vue.js を導入してぶつかった課題
      • Vue.js を採用して幸せだったこと
  • 懇親会
  • 次回開催について

当日の様子

f:id:moomoo-ya:20190308183042p:plain
RAKUS Meetup Tokyo #2 会場の様子

今回は30人の募集枠を予定していたのですが、予想外の好評につき会場をグループ企業であるラクスパートナーズのオフィスに変更しての開催となりました。

当日は雨も降る悪天候の中ご参加いただきありがとうございました。

続きを読む

puppeteerを用いてラクスのエンジニアブログに自動でアクセスしてみた

はじめに

こんにちは。エンジニア1年目のy_kwmtです。先日、業務でpuppeteerを用いてE2Eテストのテストコードを実装しました。E2Eテストとは、End to Endテストの略で、開始から終了までアプリが期待通り動くか確認するテストです。今回はpuppeteerの学習をするためにpuppeteerを用いて自動でラクスのエンジニアブログサイトにアクセスしたことについて書きたいと思います。

目次

puppeteerとは

puppeteerは、Node.jsでHeadless Chromeを自動で操作できるようにするライブラリです。puppeteerを用いることでクリック、テキスト入力、画面遷移などが自動で行えます。 公式サイトはこちらです。

github.com

導入方法

今回はこちらの記事を参考にインストールを行いました。

tech-blog.rakus.co.jp

まずはNode.jsとnpmをインストールしてください。 Node.jsはこちらからダウンロードを行い、インストーラを実行し、画面の指示に従ってインストールしてください。npmのインストールは以下を実行してください。puppeteer は操作結果を Promise で返すので、async/await が使えるv7.6.0 以降のバージョンを用意したほうがよいです。

npm init

Node.jsとnpmのインストールが完了したら、puppeteerのインストールを実行します。

npm i puppeteer

コーディング、実行

puppeteerのインストールが完了したら、コードを書いていきます。コードはこちらのページを参考にさせていただきました。

webbibouroku.com

以下のファイルを実行してラクスのエンジニアブログにアクセスします。今回は実行できているか確認するためにブラウザを表示するだけでなく、スクリーンショットも撮影しました。そのコードがこちらです。

ファイル名:sample.js

const puppeteer = require('puppeteer');

(async () => {
  //ブラウザを定義(headless:false ブラウザを表示する, true 表示しない)
  const browser = await puppeteer.launch({ headless: false });
  //タブを定義
  const page = await browser.newPage();
  //ブラウザのサイズを定義
  await page.setViewport({width: 1240, height:1080});

  //待機
  async function sleep(delay) {
    return new Promise(resolve => setTimeout(resolve, delay));
  }

  // Googleにアクセス
  await page.goto('https://www.google.co.jp/');
  // 検索窓に「ラクス エンジニアブログ」と入力
  await page.type('.gLFyf', 'ラクス エンジニアブログ');
  //スクリーンショット撮影
  await page.screenshot({path: 'google.png'});
  // 検索ボタンクリック
  //待機時間を設けないと止まってしまうことがあるので記述
  await sleep(5000);
  await page.focus('input[name="btnK"]');
  await page.click('input[name="btnK"]');
  //待機時間を設けないと止まってしまうことがあるので記述
  await sleep(5000);
  //スクリーンショット撮影
  await page.screenshot({path: 'search_result.png'});
  // 検索結果の先頭リンクをクリック
  await page.click('.rc > .r > a');
  //スクリーンショット撮影
  await page.screenshot({path: 'blog.png'});
  //ブラウザを閉じる
  await browser.close();
})();

コードを書いたら、コマンドでファイルを実行します。

node sample.js

実行中に撮影したスクリーンショットがこちらです。

f:id:y_kwmt:20190311181320p:plaingoogle.png

f:id:y_kwmt:20190311181255p:plainsearch_result.png

f:id:y_kwmt:20190311181225p:plainblog.png

最後に

今回はサイトにアクセスするという簡単な動作でしたが、puppeteerを0から始めてファイルを実行することができました。今後、また業務でpuppeteerを使うとなった時のために、これからも勉強を続けて複雑な動作を自動化できるよう頑張ります。

Copyright © RAKUS Co., Ltd. All rights reserved.