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

株式会社ラクスのITエンジニアによる技術ブログです。

知ってる?nodemailerを使ってメールを送る方法

はじめに

はじめまして。新卒入社で3年目のNIR-AMAUQAです。
今回は少し前に触ったnodemailerについて記事を書こうと思います。
具体的にはnode.jsからnodemailerというモジュールを使って、メールを送信してみようと思います。

以前nodemailerを触る機会があったんですが、調査している時に日本語の資料が少なかったり、
見つけても古いバージョンのものが多かったので、記事にしてみようと思いました。

node.jsについて分からない人はこちらをどうぞ

Node.js を5分で大雑把に理解する - Qiita

いまアツいJavaScript!ゼロから始めるNode.js入門〜5分で環境構築編〜

nodemailerとは

2010年から作られているnode.jsからメール送信を可能にするモジュールで、多くのユーザに利用されています。
ソフトウェアのライセンスはMITです。

Nodemailer :: Nodemailer

目次

nodemailerをインストール

では早速、nodemailerをインストールしたいと思います。
npmでインストールする際にモジュール名のみだと最新版をインストールします。

$ npm install nodemailer

グローバルの場合は

$ npm install nodemailer -g

インストールの確認

$ npm list --depth=0

以下のように表示されていれば成功(2017/09/06 時点での最新が4.1.0です。)

nodemailer@4.1.0

グローバルの場合は上記のコマンドと同じく末尾に-gを入れて下さい。

もし過去バージョンをインストールしたい場合は以下の書き方でバージョンを指定できます。
@の後ろにバージョン番号を書いてください。

$ npm install nodemailer@4.0.1

サンプルプログラムを作成

//モジュールの読み込み
var nodemailer = require("nodemailer");

//SMTPサーバの設定
var smtp = nodemailer.createTransport({
    host: 'localhost',
    port: 25
});

//メール情報の作成
var message = {
    from: 'Fromアドレス',
    to: 'Toアドレス',
    subject: 'nodemailer test mail',
    text: 'テストメールです。'
};

// メール送信
try{
    smtp.sendMail(message, function(error, info){
        // エラー発生時
        if(error){
            console.log("send failed");
            console.log(error.message);
            return;
        }
        
        // 送信成功
        console.log("send successful");
        console.log(info.messageId);
    });
}catch(e) {
    console.log("Error",e);
}

詳細説明

SMTPサーバ設定
//SMTPサーバの設定
var smtp = nodemailer.createTransport({
    host: 'localhost',
    port: 25
});

ここでSMTPサーバの設定を行います。
今回はローカルのメールサーバを利用した最も簡単な例です。

nodemailerの記事で探すとGmailなどのSMTPサーバを利用しているものが多いので、
外部のSMTPサーバを利用したい方はそちらを参考にしてください。

nodemailerでGmailから送信するための方法 - Qiita

メールヘッダ作成
//メール情報の作成
var message = {
    from: 'Fromアドレス',
    to: 'Toアドレス',
    subject: 'nodemailer test mail',
    text: 'テストメールです。'
};

こちらも最もシンプルなメールヘッダの例になります。

私の調べた限りではReturn-Pathの設定はできないようです。
ただし、envelopeの設定はできるのでバウンスメールなどをコントロールしたい場合は以下のようにすれば可能です。

//メール情報の作成
var message = {
    from: 'Fromアドレス', // 表示名つきにする場合は'表示名<Fromアドレス>'
    to: 'Toアドレス',
  envelope: {
        from: 'envelopeFromアドレス',  // バウンスメールの戻り先アドレス
        to: 'envelopeToアドレス'    // 実際の送信先
    },
    subject: 'nodemailer test mail',
    text: 'テストメールです。'
};

envelopeを付与した場合はto: 'Toアドレス'はなくても送信可能ですが、メールヘッダのToが無くなってしまうので書いておくのが無難かと思います。

メール送信処理
// メール送信
try{
    smtp.sendMail(message, function(error, info){
        // エラー発生時
        if(error){
            console.log("send failed");
            console.log(error.message);
            return;
        }

        // 送信成功
        console.log("send successful");
        console.log(info.messageId);
    });
}catch(e) {
    console.log("Error",e);
}

メッセージの送信に失敗するとerrorオブジェクトが返ってきます。
送信先を消してメール送信に失敗した場合の例

$ node サンプルファイル名.js  
send failed
No recipients defined

メール送信に成功すると様々な情報が返されます。
公式のリファレンスによれば以下の情報が返されているそうです。

  • info.messageId
  • info.envelope
  • info.accepted
  • info.rejected
  • info.pending
  • response

英語が苦手な私が訳すと誤解させる恐れがありますので詳しくは公式のリファレンス*1で確認お願いします。

実行してみる

以下のようになればメール送信成功です。

$ node サンプルファイル名.js  
send successful
<Message-IDが出力されている>

まとめ

今回はnode.jsにnodemailerを入れてメールを送信してみました。
想定していたよりも手軽にメール送信できました。

node.jsのモジュールに関して日本語の記事が増えてくれると嬉しいので、
私のために記事を書いてくれると嬉しいです。


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

ソフトウェアテストについて簡単にまとめてみた

はじめに

はじめまして。開発エンジニアのamdaba_sk(ペンネーム未定)です。 ラクスに新卒で入社し、今年で2年目になります。

先日ラクスオフィス内にあります共用本棚に「知識ゼロから学ぶソフトウェアテスト 【改訂版】」を見つけました。

ちょうどテストコードの書き方に悩んでいたところで勝手に自主的にこれを読みましたので、少し内容をまとめてみようと思います。

少しネットで「ソフトウェアテスト」検索するとたくさんの記事がヒットしますが、めげずに書きます。

目次

ソフトウェアのテストを分類してみる

○○テストという言葉はたくさんありますが、まずは大きく工程・品質の観点・実行方法・技法に区別されます。

工程による分類

開発の工程に対応させた分類です。

開発者側の工程に対応するテスト
  • 単体テスト
    • ソフトウェアを構成する最小の要素に対するテスト
    • 言語や開発プロセスによって「単体」の定義が異なる
  • 統合(結合)テスト
    • 単体同士を組み合わせた全体に対するテスト
  • システムテスト
    • ソフトウェアの全機能に対するテスト
    • 運用時と同じインフラ、ハードウェア、ミドルウェアを用いて行う
顧客側の工程に対応するテスト
  • 受入テスト
    • 顧客が納品されたソフトウェアに対して行うテスト
    • 自社開発など、行われない場合も多い

品質の観点による分類

どういった品質を確かめる目的で行われるのかという視点に基づく分類です。

  • 機能テスト
    • 機能が正しく実装されているかどうかのテスト
  • 性能テスト・負荷テスト
    • ストレスなく使用できる程度の実行速度がでるかどうかのテスト
    • 負荷テストでは必要な性能を満たせる限界を見極める
  • ユーザビリティテスト
    • 「使いやすい」かどうかを確認するテスト
  • セキュリティテスト
    • 外部からの攻撃に耐えられるかどうかのテスト
  • etc...

実行方法による分類

その名の通り、テストの実行方法による分類です。

  • 動的テスト
    • テストのためにソフトウェアを実行するテスト方法
  • 静的テスト
    • ソフトウェアを実行せずに行うテスト
    • コードレビュー、静的解析、etc...

技法による分類

テストのためにはどのような操作をして何を確認するかを定めた「テストケース」を作成します。テストケース作成に用いる技法による分類です。

テストケース作成技法をまとめてみる

ホワイトボックステスト(制御パステスト)

ホワイトボックステストはプログラムの論理構造が正しいかどうかのテストです。デバッガでステップ実行などしながら、それぞれの行、それぞれのブロックで実行される文は正しく書かれているか、if分やswitch文の条件は適切か、きちんと終了まで実行されるかを確認します。

このテストの実行によってカバレッジが算出され、プログラムの品質を計る一つの指標となります。

ホワイトボックステストで焦点となるのはあくまでプログラムの論理構造なので、以下のような不具合は見つけられません。

  • 要求仕様自体の誤りや不備
  • データに関するバグ
  • マルチタスクや割込みに関するバグ

ブラックボックステスト

ブラックボックステストは名前の通りプログラムを一種のブラックボックスとして扱うテストで、様々な入力に対して妥当な出力が返されるかどうかを確認します。

ですが多くのプログラムでは可能な入力の組み合わせは膨大で、それらをすべて試すことは不可能です。そこで効果的な入力をもれなく選び取る方法が考案されています。

同値分割と境界値分析

同値分割と境界値分析は、ブラックボックステスト手法の中でも基本的な手法です。

同値分割では入力全体の集合を「同値クラス」という部分集合に分割します。

同値クラスは、同じ同値クラスの入力であればプログラムの動きに本質的な違いが出ないような入力の集合です。多くはプログラムが期待する入力値である「有効同値」、そしてそれ以外のあらゆる入力値である「無効同値」に分けられます。

それぞれの入力項目ですべての同値クラスの入力を行えば、あらゆる入力に対してテストされたことになります。

境界値分析では同値クラス同士の境界に注目します。

同値クラスの境界は条件文によって分けられることが多く、これを書き間違えることでバグになります。

そこで境界をまたぐもっとも近い入力の組を入力とすることで処理の切り替えがきちんとなされていることを確かめます。

例えば…

1から10までの自然数を受け付ける入力項目に対して

  1. 0を入力1(無効同値①、境界値)⇒ 入力エラーになる

  2. 1を入力(有効同値、境界値)⇒ 正常に処理される2

  3. 5を入力(有効同値)⇒ 正常に処理される

  4. 10を入力(有効同値、境界値)⇒ 正常に処理される

  5. 11を入力(無効同値②、境界値)⇒ 入力エラーになる

デシジョンテーブル

同値分割や境界値分析は、入力項目が複数ありさらにそれらが相関している時には大変ややこしくなります。デシジョンテーブルではそれらの入力の組み合わせを表にして、各組み合わせに対して期待される出力をまとめていく方法です。

複雑な状態が絡み合う機能のテストで有効です。

例えば…

入力項目が2つあって、両方に1から10までの自然数が入力された場合のみ処理がされる場合

条件 組み合わせ
入力項目Aが1-10の範囲内 Yes Yes No No
入力項目Bが1-10の範囲内 Yes No Yes No
動作 処理実行 エラー エラー エラー
状態遷移テスト

ソフトウェアによっては「状態」が複数存在し、操作することでそれらの状態間を行き来する場合があります。状態によって受け付ける入力や出力を変化させています。

状態遷移テストはそういった場合に、入力に対して正しく状態遷移(出力)するかどうかをテストします。

ランダムテスト

ランダムテストはこれまでのブラックボックステスト手法とは毛色が違っていて、事前にテストケースなどを作成せずにやみくもに入力や操作を行うテスト手法です。

結構なバグがこれで見つかるようですが、機能要求に対するテストではあまり有効でないとのことです。ただし、セキュリティに対するファジングテストという形でランダムテストが活用されています。

おわりに

参考図書、参考ページをもとに、ソフトウェアテストの分類と、その中でテストケース作成技法についてまとめてみました。簡単ではありましたが、この記事を読んでくれた方がソフトウェアテストの勉強をするきっかけになれたなら幸いです。

参考

  1. 高橋 寿一 (著) 知識ゼロから学ぶソフトウェアテスト 【改訂版】
  2. http://gihyo.jp/dev/serial/01/tech_station/0001?page=1
  3. http://b.hatena.ne.jp/entry/qiita.com/ktarow/items/8c3d94d6c21a0c86b799

◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com


  1. 0はいろいろな意味で特別なので、仕様的に境界値でなくともテストした方が良いです。

  2. 実際はここは仕様に合わせて具体的に書きます。

【図解】はじめてでもわかるJMeterの使い方

先日、仕事でJMeterを使わせていただく機会がありました。Y-Kanohと申します。 とはいえ、新卒2年目の私には何のことかさっぱりで...先輩に教えていただきながらの作業でした。

せっかくブログを書く機会があるので、同じ境遇の人が、「え、LatencyとSample Timeってどう違うの?」「実際にテストしたらコンピュータがフリーズした!!」「2時間たっても終わらないけど、どうすれば...(焦)」とならないように、簡単な例を用いてJMeterの使い方を紹介します。

そもそもJMeterって?

JMeterApacheソフトウェア財団が開発しているオープンソースの負荷検証ツールです。 サーバに対して指定した量のリクエストを送り、そのレスポンスを受けることで、パフォーマンス計測することができます。

JMeterApacheの公式サイトからダウンロードできます。 (Javaを入れていない方は、インストールしてからご使用ください。)

JMeterGUIモードとNon-GUIモードがありますが、ここではGUIモードの説明をします。 今回は例として、サーバ192.168.99.100のtest.htmlに2つのパラメータ「param1」と「param2」を送信する例を考えます。

スレッドグループの追加

以下がJMeterの起動画面です。

ダウンロードしたファイルのbinディレクトリにあるjmeter.bat(Windows) もしくはjmeter(Unix)を実行することで開きます。

まず、テスト計画を作成するため、スレッドグループを作成します。 左上の「テスト計画」を右クリックし、 追加 > Threads(Users) > スレッドグループ を選択してください。 新しいスレッドグループが作成されます。

スレッドグループの設定画面でも設定することがあるのですが、今はひとまず置いておきましょう。

送信するHTTPリクエストの追加と設定

次にスレッドグループで送信するリクエストを設定します。

今回は一番基本的なHTTPリクエストを送るため、 左画面のスレッドグループ名を右クリックし、追加 > サンプラー > HTTPリクエスト を選択し、 作成された「HTTPリクエスト」にてWebサーバとリクエストの設定を行います。

まず、リクエストを送信するWebサーバの設定。 「プロトコル」にはhttpを入力し、「サーバ名またはIP」には負荷検証を行うサーバを指定します。

次に、HTTPリクエストの設定です。

「メソッド」には、送信メソッドを指定します。とりあえず、今回は「GET」を指定。

「パス」には、リクエス送信先のリソースを指定します。

送信するリクエストパラメータを設定します。 画面下の「追加」ボタンから複数追加することができ、パラメータの名前と値をそれぞれ指定することができます。

これで、送信するHTTPリクエストを設定できました。

スレッドグループの設定

さて、HTTPリクエストが設定出来たら、スレッドグループの設定に戻りましょう。

スレッドグループでは、先ほど設定したHTTPリクエストをどのように、どれぐらいの量、どれぐらいの期間で送信するかを設定できます。*1

これらを決定するのが、スレッド数、Ramp-Up期間、ループ回数 です。

Ramp-Up期間

Ramp-Up期間が一番わかりやすいでしょうか。

Ramp-Up期間は、全リクエストの作成時間です。

「スレッド数」で設定したリクエスト群を、何秒間で作成するかを決めるのがRamp-Up期間です。

例えば、Ramp-Up期間を100(秒)、スレッド数を10とすると、 JMaterは100秒かけて10スレッド分のリクエストを送信しようとします。

ただし、Ramp-Up期間はあくまで「リクエストの作成時間」であり、テストの実行時間ではありません。 負荷検証するサーバの処理速度がテストに追いつかない場合は、この時間を大幅にオーバーしてしまいます。

もし、一定時間でテストを中断したい場合は、同画面の「スケジューラ」にチェックを入れて、終了時間を設定してください。

スレッド数とループ回数

スレッド数は、「リクエスト群を送信する回数」のことです。

ここで重要なのことは、スレッドは「リクエスト」ではなく「リクエスト群」であること。

1スレッドでは複数のリクエストを送信することができます。

では、この「リクエスト群」内のリクエスト数はどうやって設定するかというと、「ループ回数」で指定します。

要するに、ループ回数は「1スレッドで送信するリクエストの量」を決める値です。

テスト実行時に送られる総リクエスト数は、この「スレッド数」と「ループ回数」の積によって決まります。

総リクエスト数 = スレッド数 × ループ回数

スレッド数 = 総リクエスト数ではありませんよ。

この3パラメータの関係を時系列で図にまとめると、以下のような感じですね。

また、スレッドグループでは、スケジューラを用いることでテストの開始時間や終了時間を設定できます。

テスト実行中はリクエストを送信する端末にも負荷がかかるため、これで夜間などにテストを実行させておけば楽(?)できますよ。

テスト計画作成の注意点

スレッド数、Ramp-Up期間、ループ回数 を用いてテスト計画を作ることができますが、ここであまりに大量のリクエストを投げようとすると、 JMeterを実行する端末のCPUが食い散らかされてしまします。

デフォルト設定のJMeterは、たとえRamp-Up期間が長時間だったとしても、テスト開始と同時に、スレッド数で指定したスレッドを作ってから、テストを実行するそうで、スレッド数の量によっては、一発でフリーズしてしまいます。*2

この場合、スレッドグループの設定画面にあるDelay Thread creation until neededにチェックを入れることで、スレッドの作成をずらすことができます。*3

JMeter has an option to delay thread creation until the thread starts sampling, i.e. after any thread group delay and the ramp-up time for the thread itself. This allows for a very large total number of threads, provided that not too many are active concurrently.

Apache JMeter - User's Manual: Best Practices

リスナーの追加

テストの実行結果を表示するリスナーを追加します。

左画面のスレッドグループを右クリックし、 追加 > リスナー > 結果を表で表示 を選択します。

続けて 追加 > リスナー > 統計レポート も追加しておきます。

他にも下図のように様々な結果の表示方法があるので、用途によって使い分けてください。

ただし、あまりリスナーを増やしてしまうと、メモリをたくさん使ってしまいますので、必要最低限にする必要があります。

(特に、今回用いる「結果を表で表示」は、全サンプルの結果を表示するのでたくさんメモリを使ってしまうそうです。)

また、各リスナーは、テスト実施前にファイル名を指定することで、全てのデータをファイルに出力することができるので、 テスト結果に対して実行後に何らかの処理を加えたい場合は指定してください。

ここまでで作ったテスト計画は、ファイルとして保存できます。

テスト計画を選択したうえで保存ボタンを押下し、保存しておきましょう。

テスト計画の実行と結果の見方

いよいよテスト実施です。

まずはあまり負荷が高くない条件で動かしてみましょう。

画面上部の「開始」ボタンでテストを開始でき、テストを開始すると、画面右上のアイコンが緑色になり、終了すると灰色に戻ります。

以下の画面では、スレッド数:5、Ramp-Up期間:10秒、ループ回数:20 でテストを実施した場合の「結果を表で出力」画面です。

表項目それぞれの意味は次の通り。

項目名 意味
Sample リクエストの番号
StartTime リクエストの送信を始めた時間
Sample Time(ms) リクエストの送信からレスポンスを受け終わるまでにかかった時間
Status レスポンスのステータスを示す
Bytes 受信データのバイト数
SendByte 送信したバイト数
Latency リクエストを送ってからレスポンスが届いた時間
Connect Time(ms) JMeterがサーバとの接続確立にかかった時間

ちょっと時間にかかわる用語がややこしいので、図で説明します。 また、結果をファイルへ出力する際に出力できる「Elapsed time」についても併せて説明します。

JMeterが1リクエストを送信してレスポンスを受信するまでの処理は、上の図のように行われます。

Start Timeはその名の通り、処理を開始した時刻です。(結果をファイル出力した場合はマシンタイムで表されます。)

JMeterは、処理開始後、サーバとのHTTP接続の確立を行います。この接続の確立にかかる時間がConnect Timeです。 もし、このConnect Timeに時間がかかる場合、JMeterからの接続要求が待たされている可能性があるので、サーバの同時接続条件などを見直したほうがいいかもしれません。

JMeterは、接続が確立されると、リクエストを送信し始めます。

全てのリクエストが送信されると、サーバの処理が終わるまで待機し、サーバからレスポンスが返ってくるとレスポンスを受信し始め、すべてのレスポンス情報を受け取ると処理終了となります。

余談ですが、JMeterはブラウザと違い、受信したレスポンスに対して処理を行いません。 したがって、(当たり前ですが)JavaScriptのようなブラウザ側での処理は、JMeterの結果に影響することはありません。

Elapsed Timeはリクエストを送信し始める直前から、すべてのレスポンスを受信した直後までの時間です。

Latencyは、日本語に訳すと「潜時」と言って、「刺激が与えられてから反応するまでの時間」のことです。

JMeterでは、「処理開始時間」から、「最初のレスポンスが返ってきた直後」の時間を指します。

(少しややこしいのですが、JMeterの公式リファレンスの「Connect Time」の項によると、LatencyはConnect Timeを含んだ時間になるそうです。そのため、接続エラーが起きたリクエストでは、Connect Time = Latency になります。)*4

Sample Timeは、これらの処理すべてにかかった時間です。

ちなみに、全リクエストの通し番号である「Sample」は、この終了時間の昇順で割り当てられているらしいので、Start Timeが前後していても気にしなくていいそうですよ。*5

「統計レポート」リスナーには、全サンプルの統計情報が記載されます。

たくさんのリクエストを送信するテストの場合、どうしてもすべてを見ることは不可能なので、統計情報を参考にしてください。

おわりに

さあ、これでざっくりですが、JMeterの基本的な機能は使えるようになりました。

リクエスト数を増やして、いざ、テスト! ...と考えた方、ちょっと待ってください!

これだけ説明しておいてですが、ApacheGUIモードでの本番テストを推奨していません!! *6

Don't run load test using GUI mode !

 

GUI mode should only be used for creating the test script, NON GUI mode must be used for load testing

Apache JMeter - User's Manual: Getting Started

Non-GUIモードのほうがより正しい結果を得られるため、GUIモードはテスト計画の作成のみに使い、実際のテストはNon-GUIモードを使ってほしいそうです。

斯く言う私も、この記事を書くため公式ドキュメントを読んで気づきました(^^;)

より正確な結果が求められるテストを行う場合は、GUIモードでテスト計画を作成、上部メニューの保存ボタンから保存したのち、 Non-GUIモードから読み込んでお使いください。

以上、基本的な内容ですが、私が業務で使ったJMeterの使い方について、説明しました。

もし、はじめての負荷検証であたふたしている人の助けになれば、幸いです。


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

WIP制限の大切さ

はじめに

はじめまして。開発エンジニアのstrongWhiteです。

ラクスに入社して今年で2年目になります。

今回は、仕事を進めていく上でWIPを制限する大切さをお伝えしようと思います。
堅苦しい話にならないように、あるゲームの内容をもとにお伝えできればなと思います。

WIP

WIPとは「work in progress」の略で、仕事が進行中である あるいは 仕事が完了状態ではないことを意味します。
簡単にいうと、やりかけの作業 ということになります。

突然ですが、みなさんは仕事ができる人 や 仕事が早い人と聞くと、どんな人をイメージされるでしょうか。
いろいろな仕事を同時並行的にこなしている人をイメージされますか?

実は仕事を同時並行的に行うと、かえって完了が遅くなります。
仕事ができる人 や 仕事が早い人は、ひとつひとつの仕事を確実に終わらせる人です。
ここが今回の記事の肝になりますので、念頭に置いておいてください。

コインゲーム

先日、社内で開催された勉強会でコインゲームを開催しました。
このゲームはWIPを制限する大切さを実感できるゲームです。

ゲームに必要なもの

  • コインをひっくり返す「作業者」
  • 作業者の作業時間を計測する「管理者」
  • 1人の「顧客」
  • テーブル
  • 同じサイズのコイン20枚
  • ストップウォッチ(あるいはストップウォッチ機能付き携帯電話)
  • 結果を書き出す紙

遊び方

作業者と顧客はテーブルを囲んで着席します。
1人の作業者の後ろに1人の管理者が付き、管理者はストップウォッチを持ちます。
また、顧客もストップウォッチを持ってスタンバイします。

作業者・管理者・顧客の役割はそれぞれ以下の通りです。

  • 作業者…すべてのコインをひっくり返して、次の作業者に渡す。(最後の人は顧客に渡す。)
  • 管理者…作業者がコインをひっくり返すのにかかった実質作業時間を計測する。
  • 顧客…最初のコインが届くまでの時間とすべてのコインが届くまでの時間(最後のコインが届くまでの時間)の2つを計測する。

ゲームは3回繰り返してプレイします。
最初は20枚のコインを一括で行い、2回目は5枚ずつに分けて行います。そして最後は1枚ずつに分けて行います。
勘のいい方はこの時点で気付いたかもしれませんが、このゲームでは、コインがひとつのWIPを示しています。
3回とも全く同じようにプレイしますが、違うのはWIPが徐々に小さくなっていくことだけです。

今回、勉強会では作業者3名、管理者3名、顧客1名の計7名でゲームを行いました。
結果は以下の通りです。

20枚 5枚 1枚
Aさん 20秒 28秒 28秒
Bさん 23秒 26秒 28秒
Cさん 21秒 28秒 29秒
最初のコイン 67秒 23秒 4秒
合計時間 67秒 42秒 31秒

ゲームから学べること

WIPが小さくなるにつれて作業者の作業時間は長くなりますが、最初のコインがゴールするまでの時間と合計時間は短くなります。 つまり、同時に作業する作業項目を減らすと、リードタイムが短くなるということになります。
ひとつひとつのコインを皆さんが仕掛っている仕事に当てはめると、同時並行的に仕事をするとすべての仕事が完了するのにとても時間がかかってしまうということになります。 この点から、WIPを減らすことによる重要性が理解できるかと思います。興味がある方はぜひ周りの人とゲームをプレイしてみてください。

まとめ

今回はWIPを制限する大切さをお伝えしました。効率的に仕事を進めるには、ひとつひとつの仕事を確実に終わらせるように立ち回ったほうがいいということが少しでも伝われば幸いです。
抱えている仕事が多いと、つい気が焦って何でもかんでも手をつけてしまいがちです。ですがそのまま進めても何もかもが中途半端に終わってしまい、何ひとつ完了している仕事がないという状況に陥ります。
そんなときは今回の記事を思い出していただき、WIPを制限していま取りかかっている作業を終わらせることに集中してみてください。

参考

Marcus Hammarberg、Joakim Sunden 著 『カンバン仕事術-チームではじめる見える化と改善』

続いて3年!月1開催の社内有志イベント「ビアバッシュ」の紹介

はじめに

はじめまして。エンジニアのnorthmkyです。
ラクスに新卒で入社し、今年で2年目になります。

他エントリが技術の内容だったので少し趣向を変えて
ラクスが行っている技術交流会、ビアバッシュを紹介したいと思います。

ビアバッシュとは

"ビア"とついている通り
「ビールなどのアルコールを片手に(+軽食)フランクに技術内容について発表したり語り合う交流会」
のことを指します。

だいたい月に一度くらいの頻度で有志が集まって開催しています。
参加費は...なんと無料です。
というのも技術交流会を会社が応援してくれていまして補助金がでるのです。
そのおかげもあり、ラクスでは本イベントが3年も途切れることなく続いています。
(実はここまで会社内で技術イベントが続いてる事例は少ないんだそうです)

ビアバッシュの流れ

以下のような流れでやっています。

  1. ビアバッシュ開始
  2. お酒をたしなみつつ...
  3. 発表スタート!!
    • (発表 + 質疑応答) x 3名ほど
  4. 発表が終わりと思いきや...
  5. 飛び入り参加枠スタート
  6. ビアバッシュ終了

発表後半になると聴いていた参加者側の人が登壇したくなり、
飛び入り参加枠で話し始める...ということが結構あります。

気になる発表内容ですが...実に幅広いです。

  • 話題の技術を使ってみた
  • 勉強したことを整理してみた
  • 実務をしていて身につけたTips紹介
  • 読んだ本(技術書あるなし問わず)の紹介
  • 実務をしていて感じたこと・大事だと思うこと
  • 勉強会レポート
  • 趣味について熱く語る
  • 新卒一年目で感じたこと

などなど。
熟練エンジニアから新卒で入りたての人まで、様々な人が登壇します。

前回の様子はこちら

では実際に前回ビアバッシュの様子の一部を紹介したいと思います。
f:id:northmky:20170808104118j:plain:w250

開催前、司会進行のスライドです。
開催前に参加可否のアンケートをとり、発表者とそのテーマをタイムテーブルに落とし込みます。
たまに発表はじまりの前、後に個人で宣伝したいことを宣伝する時間をとることがあり、
そのときもこの資料に記載しています。
「平日毎○曜日、勉強会開催してるよー」だったり「趣味のイベント参加者募集!」だったり
技術以外の宣伝もあります。

f:id:northmky:20170808104122j:plain:w250

軽食といいながらお寿司がでちゃいます。
その会の運営している人のさじ加減で内容は変わります。
写真では伝わりませんが、BGMも流しています。
テンションがあがります。

f:id:northmky:20170808104126j:plain:w400

実際の発表風景です。
お気づきかもしれませんが、本ブログのTOP画像の場所、 通称「コワーキングスペース」にて行いました。
この写真の登壇者の発表内容は数学よりの話だったので皆さん真剣に耳を傾けています。

上記のような感じで毎月やっています。
飛び入り枠の雰囲気もお伝えしたかったのですが、自身が飛び入りをしたのでお見せする写真はありませんでした...

ビアバッシュのよいところ

私が参加してみてよいなあと思うところは
「普段仕事で関わる/関わらない人にかぎらず興味深い話が気軽に聞ける」
ところかなと思います。
なかなか他部署のエンジニアの方と話す機会って業務ではなかなかないのではないかと思います。
また同じ部署でも話さなかった人って実はいたりして、そのいう方々の話を聴くと
案外自分が気になっている情報を持っていらっしゃったりして、そこからより関係性が深まることもあります。
自分の好きな技術の話になりますと、やはり発表者もイキイキした表情と声で発表しているので、
伝染して楽しい気持ちになりますし、もっと知りたい!という知識欲をかりたたせられます。

おわりに

ラクスでのビアバッシュを紹介しました。

お酒が入った中自由に技術の話をする/聴くのはやはり楽しいです。
そしてこのイベントを会社が推奨してくれるのもありがたいなと思います。
これからも続いていけるようにしていきます。

実は、外部の方を招いて勉強会をしようという声も上がっています。
その時はまた周知しますので気になった方はぜひ参加してみてくださいませ。

以上northmkyからのビアバッシュ紹介でした。

ソートアルゴリズムで見るプログラムの計算量

はじめに

はじめまして。開発エンジニアのCarboxyです。
ラクスに新卒で入社して、今年で2年目になります。

今回は、新卒(≒エンジニア初心者)が、効率の良いプログラムを書けるようになるきっかけになればと思い、プログラムの計算量の求め方とその比較方法をソートアルゴリズム(選択ソート)を例に紹介します。

計算量とは

ある問題を解くためにどのくらい計算が必要かどうか(どのくらい時間がかかるか)

アルゴリズムの性能評価に使用できる。

O(オーダー)記法を用いて示す。
※計算量には時間計算量と空間計算量があるが、この記事では時間計算量の事を指す。

O(オーダ)記法

計算量の一般的な記述方法。大まかな時間計算量を表す。
例として、入力サイズ n の関数として表される時間計算量T(n)が

{ \displaystyle T_{(n)} = 10n^2  + 100n + 1000}

で与えられる場合、オーダー記法では最も次数の高い項の係数を省いて

{ \displaystyle O(n^2)}

となる。なぜこのように最も次数の高い項(主要項)の係数を省くような、漸近的な評価が使われるかというと、入力サイズ n が十分に大きい場合は、時間計算量は主要項にのみ依存するからである。

選択ソート

選択ソートを例に計算量を考える。
選択ソートは最も基本的なソートアルゴリズムの1つで、次のようなアイデアに基づきソートを行っていく。

1,入力データの中から最大のデータを見つける。
2,見つけた最大のデータをソートの対象から除外する。
3, 1と2 の操作を n - 1 回繰り返す。

ソースコード

入力サイズ n の配列 D[0]、D[1]、・・・、D[n-1]

for (i=n-1; i>0; i=i-1) {
max = D[0];
maxIndex = 0;
for (j=1; j<=i; j=j+1) {
if(D[j]>=max) {
max = D[j];
maxIndex = j;
}
}
swap(D[maxIndex],D[i]);
}

このアルゴリズムは、2重のfor文により構成されている。変数 n に依存する i , j の2重ループなのだからO(n^2)になることは安易に想像できるが、計算すると次のようになる。

外側のfor文の繰り返し実行回数は n - 1 回であり、内側のfor文は外側のfor文の変数 i に依存し、i 回の繰り返しとなっている。したがって、このアルゴリズムの計算量は、以下の式で表される。

{ \displaystyle O(1) × \sum_{i=1}^{n-1}i}

{ \displaystyle =O(1) × \{1 + 2 + 3 + ... + (n-1)\} }

{ \displaystyle =O(1) × \frac{n(n - 1)}{2}}

{ \displaystyle =O(n^2)}

計算量の比較

複雑になるため詳細は省略するが、その他のソートアルゴリズムの計算量を計算すると、例えばクイックソートの場合はO(n logn)になる。オーダー記法の漸近的な大小関係は以下のようになることから、選択ソートとクイックソートを比較するとクイックソートのほうが計算量が小さい事が数値的にわかる。

{ \displaystyle log n < \sqrt{n} < n < n log n < n^2 < n^3 < ... < 2^n <n!}

まとめ

オーダ記法によって漸近的な時間計算量を示すことができる。
プログラムを実行して時間を測定しなくとも、入力サイズ n に対してどのアルゴリズムが一番速いか数値的に比較できる。

【新米エンジニア向け】ログ調査に便利なLinuxコマンド

はじめに

はじめまして。開発エンジニアのwest-cです。
ラクスに新卒で入社し、今年で3年目になります。

ラクスでもエンジニアブログをはじめることになりました。
記念すべき1エントリ目を書くことになり光栄です。

本題

そんな1エントリ目のテーマですが、現在、私自身が新卒メンバーの育成を担当していることもあり、今年入社した新米エンジニアを対象にお話をしたいと思います。

大学や会社の研修でプログラムは学ぶかと思いますが、ログの見方・調査方法についてしっかり学んだことのある方は少ないのではないでしょうか。

個人で作成したプログラムであればエラーが発生したとき程度しか見ないログですが、お客様に提供するアプリケーションとなると話はちょっと変わってきます。
ログは、ユーザがとった行動の証跡(証拠)となることから、利用状況の把握から問題が発生した場合の原因特定まで非常に重要な役割を担います。

ログの形式はソフトウェアによって異なるためそれぞれの公式ドキュメントに譲るとして、ここではログ調査にあたり知っておくと便利なLinuxコマンドを紹介したいと思います。
なお、今回は Apache のアクセスログを例として説明を行います。

リアルタイムでログを監視したい

$ tail -f access_log

ファイルの末尾が更新されると自動的に追加分が表示されます。
例えば、検証環境にて画面遷移をした瞬間のログを確認したい場合などに重宝します。
長いスタックトレースを確認する場合は、予めEnterキーでいくつか改行を入れておくとログの切れ目が分かりやすくなり便利です。

ログをスクロールして表示したい

$ less access_log

行数の長いファイルの場合、catでファイルの中身を見ようとすると画面に収まり切らず、目的のログに辿り着くのにひと苦労します。
そのようなときにlessを利用すると、スクロールしながら閲覧することができます。
lessコマンド内で利用できる操作のうち、個人的によく使うものは以下になります。

キーバインド 説明
b 1画面分上にスクロール
スペース 1画面分下にスクロール
g ファイル先頭に移動
G ファイル末尾に移動
/文字列 ファイル内を文字列で検索
n 次にヒットした検索文字列の行に移動
N 前にヒットした検索文字列の行に移動
F リアルタイムで監視(tail -fと同様)
q lessコマンドを終了する

表示する行を絞り込みたい

以降は、以下のようなアクセスログを前提として説明を行います。
(GET or POST の前の数値はリクエスト処理にかかった時間(単位:秒)、末尾の数値はレスポンスサイズと解釈してください)

$ cat access_log
192.168.10.11 - - [10/Oct/2000:13:55:36 -0700] 1 "GET /index.php HTTP/1.0" 200 2326
192.168.10.11 - - [10/Oct/2000:13:55:36 -0700] 0 "GET /top.jpg HTTP/1.0" 200 310
192.168.20.8 - - [10/Oct/2000:13:56:01 -0700] 10 "POST /login.php HTTP/1.0" 200 1793
192.168.30.50 - - [10/Oct/2000:13:57:11 -0700] 5 "GET /mypage.php HTTP/1.0" 200 831
192.168.30.50 - - [10/Oct/2000:13:57:11 -0700] 0 "GET /room.png HTTP/1.0" 200 4530

特定の文字列が含まれる行のみを抽出したい場合はgrepの出番です。

$ grep "login" access_log
192.168.20.8 - - [10/Oct/2000:13:56:01 -0700] 10 "POST /login.php HTTP/1.0" 200 1793

ファイルから「login」という文字列が含まれる行のみが抽出されました。

逆に「login」という文字列を含まない行を表示する場合は、-vオプションを付けましょう。

$ grep -v "login" access_log
192.168.10.11 - - [10/Oct/2000:13:55:36 -0700] 1 "GET /index.php HTTP/1.0" 200 2326
192.168.10.11 - - [10/Oct/2000:13:55:36 -0700] 0 "GET /top.jpg HTTP/1.0" 200 310
192.168.30.50 - - [10/Oct/2000:13:57:11 -0700] 5 "GET /mypage.php HTTP/1.0" 200 831
192.168.30.50 - - [10/Oct/2000:13:57:11 -0700] 0 "GET /room.png HTTP/1.0" 200 4530

grep -Eまたはegrepを利用すると、検索文字列に正規表現を利用することができます。

上記を組み合わせると、画像ファイル(*.jpg, *.gif, *.png)を除外したログを表示したい場合に、以下のように記述することができます。

$ egrep -v "\.(jpg|gif|png)" access_log
192.168.10.11 - - [10/Oct/2000:13:55:36 -0700] 1 "GET /index.php HTTP/1.0" 200 2326
192.168.20.8 - - [10/Oct/2000:13:56:01 -0700] 10 "POST /login.php HTTP/1.0" 200 1793
192.168.30.50 - - [10/Oct/2000:13:57:11 -0700] 5 "GET /mypage.php HTTP/1.0" 200 831

表示する列を絞り込みたい

例えば以下の3つの情報がログ調査に必要であるとします。

  • アクセス日時
  • リクエストURL
  • リクエストにかかった時間

この3つ以外の情報は今回は必要の無いノイズ情報ですので、awkで表示する列を絞り込みましょう。

awkで列を絞り込む場合、デフォルトでは空白(スペース)またはタブ単位で区切られます。
今回の例だと、4列目(アクセス日時)・6列目(リクエストURL)・8列目(リクエストにかかった時間)だけを表示したいことになります。

$ awk '{print $4,$6,$8}' access_log
[10/Oct/2000:13:55:36 1 /index.php
[10/Oct/2000:13:55:36 0 /top.jpg
[10/Oct/2000:13:56:01 10 /login.php
[10/Oct/2000:13:57:11 5 /mypage.php
[10/Oct/2000:13:57:11 0 /room.png

必要な情報のみが表示され、見通しが良くなりました。

$の後の数字には、区切り文字で行を分割した際の順番が入ります(1始まり)。
区切り文字を変更したい場合は、-F '区切り文字'とオプションを付与すれば良いです。

ちなみにcutコマンドでも同様のことは実現できますが、次に紹介する話との関連で、ログの確認時にはawkを利用することをおすすめします。

条件に合致するログのみを抽出したい

ひとつ前の例に追加して「リクエストに3秒以上かかったログのみを抽出したい」場合を考えてみましょう。
awkプログラミング言語なので、条件分岐を記述することもできます。

$ awk '$6>=3{print $4,$6,$8}' access_log
[10/Oct/2000:13:56:01 10 /login.php
[10/Oct/2000:13:57:11 5 /mypage.php

このように「○番目の項目が□□だった場合」と記述することができるため、単純な文字列一致の条件の場合でもgrepよりも細かく絞り込みを行うことができます。

まとめ

私自身、入社したての頃にログファイルをviで開いて怒られたりログファイルを根こそぎExcelに貼り付けてちまちま絞り込みを行ったりと苦い経験があったため、今回このテーマを選ぶことにしました。

今回取り上げた内容は基本的なものであり、さらに高度なログ集計を行おうとすると、sortuniqsedなども必要になるかと思います。
まずはこの記事を足がかりに、その他のコマンドも習得してステップアップしてもらえると嬉しいです!


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

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