mixi engineer blog

ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

新卒研修の受講レポート~git編~

はじめに

はじめまして、2017年新卒エンジニアの親川と玄馬です。 本記事では、git研修でおこなった内容や得た学びについて紹介したいと思います。

そもそもgitとは何なのか、という方は以下のサイトを参考にしてください。

Gitを使ったバージョン管理【Gitの基本】 | サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ

研修の様子

前半は、先輩社員による座学形式の研修でした。gitを楽しく学ぼう、ということで内容は

  • gitの使い方

  • commitとbranchについての解説

  • 歴史の取り込み方(merge, rebase)

となっていました。 研修で使用した資料は以下のページで見ることができます。

すごいGit楽しく学ぼう // Speaker Deck

gitの使い方ではリポジトリの作り方から、変更のステージング方法、commit・pushの操作、branchの操作を学びました。
操作だけでなく、commitやbranchはどういったデータ構造で表現されているかを知ることができ、この後に学ぶmerge操作の理解における大きな助けとなりました。
歴史の取り込み方の学習として、merge操作でのオプションによる動作の違いを学びました。
後半は演習として、gitを使う上で起こるトラブルを解決する「git challenge」の過去問に挑戦しました。問題は難易度別に分けて出題されるので、自分のレベルにあったものから解答することができました。
前半で学んだ操作を使いつつ、理解不足な情報は調べたり先輩社員や同期に質問して各自のペースで進めていきました。

f:id:mixi_engineers:20170828132541j:plain

ちなみに実際のgit challengeは、gitに関する問題にチームで挑戦し、時間内にいくつ解けるか!…という弊社主催の学生向けの技術イベントです。(第5回大会では4時間で18問に挑戦したそうです。)

問題の解き進め方

git challengeは、1問ごとに、以下のような流れで進めていきます。

  1. 問題のリポジトリをclone

  2. 問題の指示通りの状態になるようにリポジトリを修正

  3. push

すると、採点サーバで自動的に問題の正誤が判定され、全体のランキングページで結果を閲覧できるようになります。
「pushが出来ない」という同僚を助けるようなシチュエーションや、そもそもcloneすらできないリポジトリもあり、様々な問題に対して解決案を模索していきます。
最後まで解けないような難しい問題もありましたが、終了後に解説をしてもらえたので非常に勉強になりました。

ちなみに、git challengeの問題の解き方だけでなく、自動採点などのインフラの話が気になる方は、以下のブログを是非読んでみてください。

git challengeの自動採点高速化に向けたインフラのハナシ - mixi engineer blog

得た学び

今回の研修でcommitについての理解を深めることができました。ここでは、commitについて学んだことを紹介したいと思います。

皆さんはgitの仕組みについて、どのように理解しているでしょうか?
私は、「変更があった差分情報を時系列に保存し、いつでも過去の状況に戻れる」といった大まかな理解しかしていませんでした。
git研修が始まり、commitが持つ「Revision」という値が、gitの仕組みを理解する上で重要だということに気づきました。
commitの大まかなデータ構造は、以下の通りです。

commitのデータ構造

Revision commitのSHA-1ハッシュ
Tree ファイルのスナップショット
Parent ひとつ前のcommitのRevision
Author commitを作成した人
Committer commitを適用した人

Revisionとは、commitに対応する以下のようなハッシュ値です。
6fe9db43763ded8bbfd0b428894baa9bfc0b7d42
gitの操作をする上で、このRevisionは多くの場所で登場します。

commitのデータ構造の中にも、Parentという値にひとつ前のcommitのRevisionが入っています。
ひとつ前のcommit、そのひとつ前のcommit・・・と辿って行くことで、一番最初のcommitまで見ることができます。

branchのデータ構造にもRevisionが登場します。
私はbranchについて、枝を伸ばす・枝を分けるといったイメージを持っていました。しかしbranchの正体は、あるcommitのRevisionを指すポインタのようなものでした。
branchが指しているRevisionを新しいcommitのRevisionに変更することで、枝が伸びる・枝が分かれるような処理を実現しています。
意外と単純な仕組みだと思いませんか?これを知って、私はgitの仕組みの理解がしやすくなりました。

普段gitを使う際に、私はこれらのことをそれほど意識せずに使っていました。
しかし、データ構造や実際に行なわれる処理といった仕様を知ることで、branchやmergeについて曖昧だった部分も理解しやすくなります。
そういった理解ができていることで、gitで困った時の対応力が大きく改善されると実感しました。

おわりに

今まではgitのコマンドの機能や実行結果を把握している程度でしたが、改めて詳細な仕様を知り、実際に行われている処理を考えながらgitを使えるようになりました。
この記事を見て、gitに興味を持った方は、ぜひgit challengeにご参加下さい!
また、git challengeの概要や今までの様子などがまとまっている以下のページもぜひご覧ください。

mixi GROUP presents「git challenge」

問題の一部は以下に公開されていますので、興味がある学生の方は挑戦してみてはいかがでしょうか?
第1回git challengeの出題内容を一部公開します - mixi engineer blog

新卒研修の受講レポート~AWS編~

AWS研修

みなさま、はじめまして!ミクシィ2017年新卒エンジニアの田村と金銅です。

今回は5月10日から3日間に渡っておこなった新卒エンジニア対象のAWS研修について書きたいと思います。 研修はミクシィのオフィスにAWSの外部講師をお招きし3日間みっちりとAWSの基礎から、実例を踏まえた応用まで教わりました。

まず、「AWSとは?」という方もいらっしゃると思いますので軽く説明しますと、AWSはウェブサービス、モバイルアプリケーション、ゲームなど様々なサービスの基盤となるインフラです。従来、大規模なインターネットサービスを運営しようとするとサーバ用に専用のハードウェアを購入し、データセンターに場所を借りて設置しに行く必要がありました。しかし、このAWSはいわゆるクラウドサービスなので実際のハードウェアを意識せず開発者がアプリケーションの開発や運用に集中できるというメリットがあります。

研修を大きく分けると講義と実際に習ったことを構築する実践形式のラボ、そしてチームで行ったインフラ設計のディスカッションといった内容でした。

初日

講義では可用性について学びました。

アプリケーションのインフラでは可用性がとても重要です。可用性とはシステムがいかにダウンせずに利用できる状態を保てるかという指標で、これが高ければ高いほどインフラの質が良いことを示します。

これには、急激なアクセスの増加によって負荷が増大した際にも耐えられるスケーラブルなインフラ構成をとる必要があり、まさにクラウド型のサービスであるAWSはこのような要求にうってつけです。

初日のラボではAWSのサービス群の中からVPC, EC2, DynamoDB, S3, IAMを使用し、障害を見据えたスケーラブルなウェブアプリケーション環境を構築しました。

f:id:mixi_engineers:20170822142839j:plain

二日目

二日目は、すでに自社が運用しているインフラ環境を想定し、それをクラウド上に持って行くフォークリフトという作業をチームでディスカッションし、その内容をホワイトボードに書いて発表しました。

ここで同期や講師の上原さんから鋭いツッコミが入り、実運用を考えた上で改善すべき点を知ることができました。

また、講義ではLambdaを使ったイベント駆動のオートスケールするインフラ設計を学び、ラボでは実践でその構築方法を身につけました。これがクラウドの特徴であり、必要な時に必要な分だけの処理能力を利用することでコストを最低限に保つことができるのです。

最終日

ここまで二日間を通して可用性の重要さについて学びました。 例えば、災害でデータセンターに火災や停電が起こったらどうでしょうか。最終日の講義では、そのような滅多に起こらない場合についても冗長化を図り、サービスの提供を継続できる強固なインフラ設計を学びました。

AWSは世界中にリージョンと呼ばれる地理的に分離したデータセンターを持っており、東京リージョンで障害が発生した際には北カリフォルニアリージョンにあらかじめ作っている同じ構成のインフラに処理を引き継ぐことができます。

最後に行ったハンズオンでは、サーバレスというアーキテクチャに沿って掲示板のウェブアプリケーションを作りました。サーバレスといってもサーバが存在しないわけではなく、AWSに管理された(フルマネージドな)サービスを使うことで全くコードを書くことなくアプリケーションの実装ができる構成のことを指します。しかし、これにはデメリットもあり、フルマネージドサービスは容易に利用できる反面カスタマイズ性が低く、細かい要求には応えられないケースがあります。そのため講師の方もおっしゃっていましたが、バランスが重要なのです。 f:id:mixi_engineers:20170822142832j:plain

まとめ

今回AWS研修を通じて、インフラは障害が起こることを前提に設計することが大切だと感じました。また、急激な変化に耐えられるようにスケーラブルな構成をとることで絶やさずサービスを提供し続けることができ、事業者もユーザもハッピーになります。

以上、AWS研修三日間のレポートでした! f:id:mixi_engineers:20170822143337j:plain

新卒研修の受講レポート~データベース編~

17新卒エンジニアデータベース研修

今回は、XFLAG事業本部 SREグループの清水さん(@isaoshimizu)によるデータベース研修で学んだことについて、新卒エンジニアの左野と坂本がレポートしていきます。

f:id:mixi_engineers:20170824103326j:plain

↑研修中の様子です

研修内容

講義は以下の内容で進んでいきました! - MySQLの基本的な話 - データベースの基本的な話 - インデックス - 負荷対策 - 運用の話 - 演習

今回は研修内容については深く掘り下げませんが、研修を受けて得られた学びと感想について私たちが感じたことを書いていきます!

今年の新卒が使ったことのあるフレームワーク

1位. Ruby on Rails

2位. Sinatra

3位. FuelPHP

いきなり蛇足ですが、研修前に扱ったことがあるフレームワークについて事前にアンケートがありまして、Ruby on Railsが人気のようでした。ORMはActive Recordが人気でした。

照合順序と寿司とビールの話

前半は、MySQLを題材にデータベースの基礎的な部分について学習しました。ACID特性やトランザクション、正規化、インデックスなどです。聞いた話の中で印象に残ったのは、寿司ビール問題と言われているもので、例えばMySQLで設定しているUnicodeの照合順序によっては🍣や🍺などの絵文字が同一扱いになったりならなかったりする問題です。詳しくは以下の記事が参考になります。

MySQL と寿司ビール問題 - かみぽわーる http://blog.kamipo.net/entry/2015/03/23/093052

インデックスの話

わたくし坂本は、過去にMySQLを利用したサービスの開発やISUCONに参加したことがあるのですが、その際、速度向上を狙いインデックスを貼ることがありました。しかし実際にインデックスがどのように作用して速度向上するのか、ということは全く理解せずにインデックスを追加していました。 今回の研修では改めてインデックスの挙動について学ぶことが出来ました。 例えば、「関数や式、否定構文、LIKEではインデックスは効かない(LIKEの前方一致では効く)」「LIMIT OFFSETはとても遅いのでWHEREで絞り込むと良い」などの注意すべき点を教わりました。これまでは、こういった点を知らずにクエリを発行していましたが、今後はどのようなクエリを発行するのか、学んだことを踏まえたインデックス設計を行いたいと思いました。

演習してみた話

最後に、演習として実際に効率の良いクエリ発行ができるか、の確認をしました。 データセットとしては、 https://github.com/datacharmer/test_db 内の employees.sql を利用しました。

演習1

USE employees;
SELECT SQL_NO_CACHE * FROM employees WHERE hire_date = '1985-02-01' AND birth_date = '1963-08-02';

このクエリを実行すると全件スキャンがおこなわれ、検索に時間がかかります。 最も短い時間で検索が行われるように工夫してください。

まずは、このまま実行をするとどうなるのかを確認します。

mysql> SELECT SQL_NO_CACHE * FROM employees WHERE hire_date = '1985-02-01' AND birth_date = '1963-08-02';
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  20539 | 1963-08-02 | Poorav     | Gecsei    | M      | 1985-02-01 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.13 sec)

この時点で0.13secかかっており既に遅いということが分かります。実際にどの程度スキャンされているのかを explain を用いて確認します。

mysql> explain SELECT SQL_NO_CACHE * FROM employees WHERE hire_date = '1985-02-01' AND birth_date = '1963-08-02';
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299290 |     1.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

rows の項目を見ると分かるように、30万件近いスキャンが走っていることが分かります。

この場合は、インデックスを追加することでスキャンする数を減らすことができます。 今回はインデックスを hire_date に追加します。

mysql> alter table employees add index hire_date_index(hire_date);
Query OK, 0 rows affected (0.48 sec)
Records: 0  Duplicates: 0  Warnings: 0

その後、同じクエリを実行すると以下のようになります。

mysql> SELECT SQL_NO_CACHE * FROM employees WHERE hire_date = '1985-02-01' AND birth_date = '1963-08-02';
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  20539 | 1963-08-02 | Poorav     | Gecsei    | M      | 1985-02-01 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.01 sec)

最初0.13secかかっていた時間が、0.01secまで短縮できました!explainでスキャン数も確認してみます。

mysql> explain SELECT SQL_NO_CACHE * FROM employees WHERE hire_date = '1985-02-01' AND birth_date = '1963-08-02';
+----+-------------+-----------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys   | key             | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ref  | hire_date_index | hire_date_index | 3       | const |   15 |    10.00 | Using where |
+----+-------------+-----------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

30万件近くスキャンしていたのが、15件まで減らすことができました! key を見ると先程設定した hire_date_index が利用されていることも確認できました。

演習2

次の演習は以下のような課題です

USE employees;
SELECT SQL_NO_CACHE * FROM employees WHERE birth_date > '1959-01-01' ORDER BY hire_date LIMIT 5;

上のクエリを実行すると、ファイルソートが発生して検索速度が遅いことが分かります。ファイルソートが起きないように工夫をしてみましょう。

mysql> SELECT SQL_NO_CACHE * FROM employees WHERE birth_date > '1959-01-01' ORDER BY hire_date LIMIT 5;
+--------+------------+-------------+-----------+--------+------------+
| emp_no | birth_date | first_name  | last_name | gender | hire_date  |
+--------+------------+-------------+-----------+--------+------------+
| 111400 | 1959-11-09 | Arie        | Staelin   | M      | 1985-01-01 |
| 110725 | 1961-03-14 | Peternela   | Onuegbe   | F      | 1985-01-01 |
| 111035 | 1962-02-24 | Przemyslawa | Kaelbling | M      | 1985-01-01 |
| 110085 | 1959-10-28 | Ebru        | Alpin     | M      | 1985-01-01 |
|  87761 | 1960-08-19 | Shir        | Munck     | F      | 1985-02-01 |
+--------+------------+-------------+-----------+--------+------------+
5 rows in set (0.14 sec)

実行結果です。0.14 sec とクエリが遅いことが確認できました。EXPLAINを使ってクエリを確認してみましょう。

mysql> EXPLAIN SELECT SQL_NO_CACHE * FROM employees WHERE birth_date > '1959-01-01' ORDER BY hire_date LIMIT 5;
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299157 |    33.33 | Using where; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

ここで Extra という項目に注目してみましょう。Using filesort からファイルソートが発生していることが確認できます。これはテーブルにインデックスが存在しないために ORDER BY で指定されたソートを行うためのメモリ使用量が増加しており、一時的な記憶領域としてファイルを利用するためクエリが遅くなります。1つ目の演習と同じように hire_date にインデックスを追加してみましょう。

mysql> alter table employees add index index_name(hire_date);
Query OK, 0 rows affected (0.40 sec)
Records: 0  Duplicates: 0  Warnings: 0

再びクエリを実行してみます。

mysql> SELECT SQL_NO_CACHE * FROM employees WHERE birth_date > '1959-01-01' ORDER BY hire_date LIMIT 5;
+--------+------------+-------------+-----------+--------+------------+
| emp_no | birth_date | first_name  | last_name | gender | hire_date  |
+--------+------------+-------------+-----------+--------+------------+
| 110085 | 1959-10-28 | Ebru        | Alpin     | M      | 1985-01-01 |
| 110725 | 1961-03-14 | Peternela   | Onuegbe   | F      | 1985-01-01 |
| 111035 | 1962-02-24 | Przemyslawa | Kaelbling | M      | 1985-01-01 |
| 111400 | 1959-11-09 | Arie        | Staelin   | M      | 1985-01-01 |
|  20539 | 1963-08-02 | Poorav      | Gecsei    | M      | 1985-02-01 |
+--------+------------+-------------+-----------+--------+------------+
5 rows in set (0.00 sec)

0.00 sec まで改善できました。EXPLAINでファイルソートが起きていないか確認してみましょう。

mysql> EXPLAIN SELECT SQL_NO_CACHE * FROM employees WHERE birth_date > '1959-01-01' ORDER BY hire_date LIMIT 5;
+----+-------------+-----------+------------+-------+---------------+------------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key        | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | index | NULL          | index_name | 3       | NULL |    5 |    33.33 | Using where |
+----+-------------+-----------+------------+-------+---------------+------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

Using filesort が消えてファイルソートが起きなくなったことを確認できました。

感想

坂本: 今までデータベースについていろいろなアンチパターンや高速化について勉強をしてきましたが、今回の研修を通じて体系的に学べたおかげで点と点が線になり、今後につながる学びが得られたと思います。今後は、業務で役に立つようにさらに勉強を重ねて自分の武器となるようにしていきたいです。

左野: 今回の研修ではデータベースについて知らないことばかりだと痛感しました。データベースの知識は業務で欠かせないものになると思うので、講義資料を読み込んで勉強していきます。

git challengeの自動採点高速化に向けたインフラのハナシ

git challengeのインフラを担当している2016年度新卒エンジニアの轟 (@tdrk18) と、2017年度新卒エンジニアでSREの見習いをやっております佐藤 (@jtwp470) です。今回は、git challengeという技術競技イベントの自動採点の高速化に向けたインフラのお話です。

続きを読む

伝承進化し続ける技術イベント: git challenge開催記念インタビュー

こんにちは、ミクシィグループ 人事部です。

今回で第6回目*1を迎える、競技型技術イベント「git challenge (ギット・チャレンジ)」開催にあたり、運営に携わるエンジニア社員の国分さんと轟さんにお話を聞いてきました。
過去5回の大会を振り返るとともに、git challengeへの想いを語っていただきます。 #mixi_git

 

f:id:mixi_engineers:20170727135539j:plain 

続きを読む

新卒研修受講レポート~テスト編~

はじめまして、17新卒エンジニアの村上と林です。

今回は「テスト」という「プログラムが正しく動作しているかチェックするためのプログラム」についての研修を受けたので、まとめていきたいと思います。

 

本研修の内容は以下のようなものでした。

・テスト/設計についての簡単な講義

・ペアプログラミングでの実習

  • 車窓からのTDD
  • 円の面積を求めるプログラムをTDD
  • emailアドレスの正誤判定プログラムをTDD

 

テストについての簡単な講義

 

テスト研修の目的

まず、なんでこんな事やるの?という事で、研修の目的について述べたいと思います。

研修の目的は「良い設計を覚える」、これだけです。

 

良い設計ってなんなの?

そこで、良い設計とは?となると思います。

疎結合?可読性?

色々あると思いますが

「経営的な要求・条件に応えられること」です!

経営判断としてスピードが求められる場合には可読性よりも開発スピードを優先する場合もあります。良い設計に重要なものはその時の状況によって変わるということです。

 

しかしながら、突然のメンバー変更や仕様変更などが往々にして発生し、保守しづらいコードでは何をしているのかよく分からなくなるため、結果的に保守しやすい設計の方が(引き継ぎなども含めて)開発スピードが早くなります。

なので今回の研修では「保守のしやすさ」に焦点を当てます。

 

いい(保守しやすい)設計方法

保守しやすい設計方法として、テスト駆動開発(test-driven development:TDD)を利用します。この手法では、大きく3段階の手順を踏みます。

  1. テストを書く
  2. テストを失敗させる
  3. 実装してテストを成功させる

この3つの手順を実施することにより保守しやすい設計になります。


TDDのメリット

メリットは以下の3点です。

・テストを先に書くので、テストしづらいコードを書けない

・テストしやすいコードは疎結合で副作用もなく分岐も少ない

・この作業をやっていくと自然に保守しやすい設計になる

 

ペアプログラミングでの実習

ここまでの講義内容をペアプロで実践しました!

(※ペアプログラミング: 2人でプログラミングすること。常に片方がレビューをやっているので様々なメリットがある)

f:id:mixi_engineers:20170510162530j:plain

車窓からのTDD

「車窓からのTDD」はweb上に公開されており、内容としても簡単なのでTDDを体験してみたい方はリンク先を確認してみてください!

http://objectclub.jp/technicaldoc/testing/stack_tdd.pdf

 

「車窓からのTDD」には対話形式でTDDのやり方が書かれており、手順通りに進めていくだけで良いため、手始めのTDDの理解にとても役立ちました。

 

「車窓からのTDD」はスタックを構築するだけの簡単な内容で、上記したTDDの流れの通り、テスト作成し失敗、実装、再度テストを実行させ成功、のサイクルで行います。これはTDDでは基本の流れになります。今回の研修では、各自経験のある言語(RubyやPythonなど)で作業を進めていきましたが、どの言語でも基本の流れを抑えれば大丈夫です。

 

テストを書いてから実装をするので、実装の目的が明確になることで無駄なコードが減り綺麗なコードになると感じました。


円の面積を求めるプログラムをTDD

この課題では、「標準入力経由で円の半径が渡されるので、円の面積を求め四捨五入して整数に丸める」というプログラムを書いていきました。

入力が外から入ってくるため入力値に対するテストが必要になります。

この課題の採点が一回しか行われないという条件だったため、絶対に正解するように多くのテストを書きました。

(テストケースをたくさん書いて置くことで途中でコードの間違いを素早く見つけることができました。間違いなく実装するという点においてもすごくテストが役に立ち、重要なんだと実感しました!)

 

また、今回の課題でのポイントは標準入力でデータが渡ってくるという点です。テスト(今回の場合ユニットテスト)はロジックだけをテストしたいので依存性がないものが理想です。標準入力に依存しないように、スタブやモックオブジェクトで切り離す方が良いでしょう。

 

emailアドレスの正誤判定プログラムをTDD

「emailアドレスが"RFC5312 addr-spec"の部分的な仕様として正当なものであればok、違えばng」のテストを作成しました。

今回の場合、大量のテストケース(ngになるメールアドレス、okなメールアドレス)が必要になります。

なので、どのテストケースで失敗したかを分かりやすくする工夫が必要でした。

 

テストの速度は上げつつ、どこで失敗したかを判別したいのですが様々な方法があるようです。Rubyの黒魔術的な方法もあるようですが、後日調べたところこのような書き方もあるようです。

qiita.com

 (テスト書いててどんなテストケースあるかなってなったとき、キレイに書いてると「このケースもあったな」となりやすいので、保守性と速度が確保されると感じました)

 

まとめ

今回の研修ではテストの重要性について学びました。

保守しやすい設計で、引き継ぎの方や後輩達に、先輩はいいコード書くやろ?ってドヤ顔しましょう!!!!

新卒研修受講レポート~セキュリティ編~

こんにちは。2017年新卒エンジニアの追田と服部です。

本記事では、4月におこなわれた新卒エンジニア向けのセキュリティ研修の大まかな概要や感想を受講者の立場からお伝えしたいと思います。

講師はXFLAG事業本部 たんぽぽGの亀山さんです。

 

内容

研修は以下の3部構成で実施されました。 

  1. セキュリティの必要性や脆弱性とその対策についての説明
  2. WebGoat(研修用やられサイト)を用いた実習
  3. スマートフォンゲームのチート事情についての解説


1. セキュリティの必要性や脆弱性とその対策についての説明
まず、企業が情報セキュリティ上の過失によって個人情報漏洩などの事故を起こしてしまった場合、どのような影響が考えられるでしょうか。
その企業の信頼の低下やイメージダウンを招いてしまうことはもちろん、それに伴う業績悪化や対応費用によって数百億円規模の損失を計上してしまう場合もあります。

本研修では過去に発生した実際のセキュリティ事故の事例を知るとともに、具体的な脆弱性の対策手法について学びました。

脆弱性の攻撃手法で最も有名なものと言えばSQLインジェクションが思い浮かぶかと思いますが、ウェブアプリケーションエンジニアが気を付けるべき脆弱性はこれ以外にも数多くあります。
IPA(情報処理推進機構)が公開している「安全なウェブサイトの作り方」によると、攻撃手法は以下の11種類に分類され、それぞれについて適切な対策をとる必要があります。

1. SQLインジェクション
2. OSコマンド・インジェクション
3. パス名パラメータの未チェック/ディレクトリ・トラバーサル
4. セッション管理の不備
5. クロスサイト・スクリプティング
6. CSRF(クロスサイト・リクエスト・フォージェリ)
7. HTTPヘッダ・インジェクション
8. メールヘッダ・インジェクション
9. クリックジャッキング
10. バッファオーバーフロー
11. アクセス制御や認可制御の欠落

次のセクションでは、研修用に用意された実際のWebサイトを攻撃することを通してこれら脆弱性を対策することの重要性を学んでいきました。

2. WebGoat(研修用やられサイト)を用いた実習
ここでは、WebGoatと呼ばれる練習用Webサイトを攻撃することで前述の様々な種類の脆弱性について手を動かしながら学びました。

f:id:mixi_engineers:20170510162020j:plain

攻撃手法についてですが、例えばBurp Suiteという脆弱性診断ツールを用いるとHTTP通信のキャプチャやリクエスト内容の書き換えを簡単に行うことができます。※悪用は厳禁です!

3. スマートフォンゲームのチート事情についての解説
ここからは、講師の亀山さんの専門分野でもあるスマートフォンゲームにおけるチートに関するお話を聞きました。
日本最大級のユーザー数を誇る、スマホアプリである「モンスターストライク」のチート対策について、実際にセキュリティエンジニアからお話を聞くことができるのはミクシィの研修ならではのことです。

資料の一部はXFLAGサイトのブログでも公開されていますので、興味のある方はぜひご覧ください。
スマートフォンゲームのチート事情(@ITセキュリティセミナー)|XFLAG ケタハズレな冒険を。
 

当日の様子(感想) 

当日印象的だったハプニングがあります。この研修ではWebGoatを使って脆弱性のあるWebサイトを攻撃してその防御手段を学ぶのですが、研修用のサーバがトラブルによってうまく動かなくなってしまったのです。

 

そんな時に同期がDockerのWebGoatイメージがあることを発見して、それぞれのPCにそのイメージを用いたDockerコンテナを立てることを立案しました。新卒同士助け合いながらそれぞれのマシンにWebGoatのDockerコンテナを立てて無事にトラブルを乗り切りました。その時は同期のチームワークを強く感じ、トラブルを通じて研修の士気が高まりました!

f:id:mixi_engineers:20170510162053j:plain

1.セキュリティの必要性や、脆弱性とその対策についての説明

 

Webサイトを作る上で脆弱性を意識して開発することの重要性はわかっていたつもりでした。しかし、これまでに起きたセキュリティ事故の事例やその被害規模を紹介されると、認識が甘かったなと感じると同時にどのようにすればセキュリティ事故を防ぐことができるのか俄然関心が高まりました!

中でもセキュリティ事故と株価の関係が紹介された時が一番盛り上がっていましたね(笑)。

 

2.WebGoat(研修用やられサイト)を用いた実習

 

Webサイトを攻撃するというのは本当なら犯罪ですが、今回はWebGoatという攻撃用のWebサイトなので安心して攻撃することができました(笑)。

このWebGoat、攻撃手法ごとに問題を解いていくようにできており、その問題量も膨大で研修時間で全て解くことは不可能なので、私は、

 

1.SQLインジェクション

2.XSS(クロスサイトスクリプティング)

 

の2つに絞って問題を解き進めました。

 

どちらも有名な攻撃手法ですが、実際に攻撃者側に立ってみて攻撃してみると、意外と簡単に情報の入手や改ざんができてしまうものだと感じました。

 

攻撃手法に詳しくなくてもネット上の情報があれば、意味を理解していなくても簡単にWebサイトを攻撃できてしまいます。攻撃が簡単にできてしまうからこそ、常に防御のことを考えてアプリケーション開発をしなくてはいけないのだなと改めて感じました。

 

3.スマートフォンゲームのチート事情についての解説

 

Webサイトに対する攻撃は多少なりとも知っていましたが、昨今のスマホゲームのチート事情がどうなっているのかは恥ずかしながら知りませんでした。

 

しかし、チートに利用できるツールが出回っており、メモリの値を書き換えたり通信内容を改変することによって簡単にできてしまうことがわかりました。ツールさえあれば中学生でも簡単にチートすることは可能です。だからこそ、しっかりと対策を練らなければいけないのだなと痛感しました。

 

ゲームの不正行為で狙われやすい箇所はおおまかに、

1.メモリデータ

2.ストレージデータ

3.ロジック

4.通信

5.操作

と分類され、データ改変や操作の自動化などが行われる可能性があります。

 

例えば、メモリデータの改変はチートでもメジャーな手法なのですが、今回弊社のモンスターストライク(以下、モンスト)を題材に考えてみます。

 

モンストでは、ガチャを引く際「オーブ」というアイテムを使用します。現在10個のオーブを所持しているとします。

不正ユーザはこのメモリ上の10という数値をプロセスメモリエディタというツールを使って数値を999に改変し、オーブを不正に増やそうとするかもしれません。

 

では、この場合どのような対策が考えられるでしょうか?

 

-メモリ上の値を暗号化する

-計算に利用する数量をクライアント側に持たない

 

など、考えられる対策はいくつかあります。

 

この時大切なのは、選んだ対策はそもそもの目的との折り合いがつく対策であるのか、などを考えしっかりと吟味することです。

 

また、サーバの処理はほぼ手出しができないので、近い将来クラウドゲーミングのように処理の大半をサーバ上で行うようになれば昨今のチート手法はほぼ無意味となるかもしれません。

 

しかし、現状はスマホ側でゲーム処理を行うケースも少なくないため、これらのポイントを押さえた対策が必要となります(操作の自動化は厳密にはチートではないが不正行為を目的に行われる事もある)。

 

また開発時は面白さや快適さを重視するので、Webアプリほどセキュリティに意識が向かないことが課題として挙がっていたことに納得すると同時に、難しさも感じました。

ゲーム開発者としてユーザに対してワクワク感を提供することを第一に考えたいけれども、そうするとセキュリティがおろそかになってしまうというジレンマは辛いものです。

 

まとめ

今回の研修では座学のみならず、実際に攻撃してみることでWebアプリを開発する上でのセキュリティの重要性を実感することができました。

 

また、昨今巷を賑わせているスマホゲームのチート対策も学ぶことができます。

アプリからゲームまで様々なセキュリティを取り扱う研修はなかなか珍しいのではないでしょうか。