TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

927

はじめに こんにちは。新卒2年目のy_kwmtです。 最近WebStorageに触れる機会があったので、 JavaScript でWebStorageのデータを保存、上書き、削除する方法について説明します。 はじめに WebStorageとは SessionStorageとは LocalStorageとは ローカル環境で実装 最後に 参考にしたサイト WebStorageとは WebStorageとは、ユーザのローカルブラウザにデータを保存する仕組みのことを言います。 WebStorageはSessionStorageとLocalStorageの2種類に分かれます。 SessionStorageとは SessionStorageへ持っている値はウィンドウを閉じるまで有効となります。 別タブ、別ウィンドウへの共有はできません。 LocalStorageとは LocalStorageへ持っている値はウィンドウを閉じたあとでも有効となっています。 別タブ、別ウィンドウへの共有ができます。 ローカル環境で実装 今回はSessionStorageを用いてボタンを押した回数を保存、削除します。 「カウント」ボタンを押してカウントを増やし、「クリア」ボタンを押して、カウントをクリアします。 <!DOCTYPE html> < html > < head > < meta charset = "utf-8" > </ head > < body > < button id = "count" > カウント </ button > < button id = "clear" > クリア </ button > < script > document .getElementById ( "count" ) .onclick = function () { sessionStorage.setItem ( 'count' , eval ( Number ( sessionStorage.getItem ( 'count' )) + 1)) ; } ; document .getElementById ( "clear" ) .onclick = function () { sessionStorage.removeItem ( 'count' ) ; } ; </ script > </ body > </ html > sessionStorage(localStorage).getItemでデータの取得を行います。 「sessionStorage.getItem('count')」で「count」というkeyを持つsessionStorageの value を取得することができます。 sessionStorage(localStorage).setItemでデータの追加、上書きを行います。 「sessionStorage.setItem('count', eval(Number(sessionStorage.getItem('count')) + 1));」で、「count」というkeyを持つsessionStorageの value を1ずつ増やした値を上書きしています。 sessionStorage(localStorage).removeItemでデータの削除を行います。 「sessionStorage.removeItem('count');」で、「count」というkeyを持つsessionStorageのデータを削除します。 ブラウザでの実行の様子がこちらです。 最後に 今回は JavaScript を用いてWebStorageの管理を行いました。 簡易的な実装しかできませんでしたが、次は時間をかけた JavaScript の実装を行い、 JavaScript の理解を深めたいと思います。 参考にしたサイト
アバター
はじめに こんにちは。新卒2年目のaa_cryingです。 最近興味本位でVue.jsについて学習を始めましたので、今回はVue.jsの基礎的な部分について紹介したいと思います。 はじめに Vue.jsとは プログレッシブフレームワークとは Vue.jsの代表的な機能 リアクティブなデータバインディング コンポーネント 高速なレンダリング おわりに 参考にした記事 Vue.jsとは Vue.jsとは、 ユーザーインターフェイス (UI)を構築するための JavaScript の プログレ ッシブ フレームワーク です。 そこで、まずは プログレ ッシブ フレームワーク とは何かについて説明したいと思います。 プログレ ッシブ フレームワーク とは プログレ ッシブ フレームワーク ( Progressive Framework ) とは、Vue.js作者のEvan You氏が提唱する概念です。 JavaScript にはVue.jsの他に jQuery 、React.js、Angular.jsなど様々な フレームワーク が存在します。 実際のプロジェクトではスタート時にこれらの中から フレームワーク を選択し、開発を進めることになります。 しかし、アプリケーションの開発を進めていくと、様々な要件に対応するためにアプリケーションの規模も大きくなっていきます。 そうすると、最初に導入した フレームワーク が合わなくなり、乗り換えるために新しい フレームワーク を模索しなければなりません。 ところがVue.jsは、サポートするツールやライブラリといったエコシステムの存在によって、アプリケーションの要求に柔軟に対応することができます。 このように、 どのような規模、段階のアプリケーションにも対応できる というのが プログレ ッシブ フレームワーク の概念になります。 Vue.jsの代表的な機能 ここではVue.jsの代表的な機能である以下3つの機能について説明していきます。 リアクティブなデータ バインディング コンポーネント 化 高速な レンダリング まずは簡単なコードの例を見ていただければと思います。 <!DOCTYPE html> <!DOCTYPE html> <html> <head> <meta charset= "utf-8" > </head> <body> <div id= "binding" ></div> <div id= "components-button" > <p><count-button></count-button></p> <p><count-button></count-button></p> <p><count-button></count-button></p> </div> <script src= "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js" ></script> <script> //データバインディングの例 new Vue( { el: '#binding' , template: ` <div> <p><input v-model= "message" ></p> <p> {{ message }} </p> </div> `, data: { message: 'Hello World!' } } ) //componentの例 Vue.component( 'count-button' , { template: '<button v-on:click="increase">{{ count }} 回押しました</button>' , data: function () { return { count: 0 } } , methods: { increase: function () { this .count++; } } } ) new Vue( { el: '#components-button' } ) </script> </body> </html> ブラウザで表示すると以下のようになります。 ブラウザでの実行 Vue.jsを簡単に導入するには cdn.jsdelivr.net からソースを参照する方法があります。 その際は以下のように記述します。 < script src = "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js" ></ script > vue@2.6.10 と記載するとバージョンを指定して使用することが出来ます。 また、Vue.jsでは、以下のように記述することで、Vue インスタンス とHTML要素との紐づけが可能です。 new Vue( { //<div id="binding"></div>と紐づけ el: '#binding' , // ...略... } ) リアクティブなデータ バインディング el: '#binding' の部分ではデータの更新とDOMの更新を同期的に行っています。 input要素に v-model というディレクティブを使用していますが、これによりリアクティブな入力データの同期を可能にしています。 v-model は、内部的には input 要素に応じて異なるプロパティを使用し、異なるイベントを送り出すという動きをしています。 そのため、v-modelではform要素にある value 等の初期値を無視してしまうので、 JavaScript 側の data オプションの中で初期値を指定する必要があります。 data: { message: 'Hello World!' } 今回は Hello World! を初期値としているため、初期表示ではそのように出力されています。 コンポーネント Vue.componentの部分では、<count-button>という コンポーネント を定義しています。 コンポーネント とは、名前付きの再利用可能なVue インスタンス になります。 new Vue で作成されたルートVue インスタンス 内 (今回はcomponent-button) でカスタム要素として使用できます。 このように再利用できるのはとても便利です。 count-buttonの中で、 v-on:click という記述があると思います。 <button v-on:click= "increase" > {{ count }} 回押しました</button> こちらはVue.js特有の v-on というディレクティブで、DOMイベント発火時の JavaScript の実行が可能になります。 今回の場合は、ボタンをclickすることで increase という関数を呼んでいます。 increase という関数はcountをインクリメントするという内容になっており、 クリックすると ○回押しました の数字がインクリメントされていきます。 また、Vue.jsではイベント修飾子というものを提供しており、それを用いてイベントを制限することもできます。 例えば、以下のように記載するとボタンが1回しか押せなくなります。 <button v-on:click.once= "increase" > {{ count }} 回押しました</button> .onceを付けた結果 他にも様々なイベント修飾子がありますので、詳細は下記リンクを参照してください。 Vue.js公式 - イベントハンドリング 高速な レンダリング Vue.jsでは Virtual DOM を採用しているため、高速な レンダリング (表示処理) を可能としています。 Virtual DOMとは、その名の通り仮想のDOMになります。 実際のDOMと同じ構造の仮想DOMを用意し、仮想DOMに対して処理を行います。そして、その結果生まれた差分だけを実際のDOMに反映します。 この仕組みを用いることで、高速な レンダリング を可能にしています。 おわりに 今回はVue.jsの基礎的な部分について紹介させていただきました。 Vue.jsには今回紹介できなかった便利な機能が沢山ありますので、 次回はもっと掘り下げて紹介していければと思います。 参考にした記事 Vue.js公式ガイド エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに こんにちは。新卒2年目のtaku_76です。 今回は Ajax についてざっくりしたことしか分かっていなかったので少し時間を確保してコードから学習することにしました。 はじめに Ajaxとは ローカル環境で実装してみる Ajaxで外部APIへ通信する おわりに 参考にした記事 Ajax とは 以下は Wikipedia の引用です。 Ajax (エイジャックス[1][2]、 アジャックス [3])は、ウェブブラウザ内で非同期通信を行いながら インターフェイス の構築を行うプログラミング手法である[4]。 XMLHttpRequest (HTTP通信を行うための JavaScript 組み込みクラス)による非同期通信を利用し、通信結果に応じてダイナミックHTML (DHTML) で動的にページの一部を書き換えるというアプローチを取る[5]。 Ajax はAsynchronous JavaScript + XML の略で、2005年2月18日に米国のインフォメーションアーキテクトであるJesse James Garrettにより名付けられた[5][6][7]。 他のサイトも見てみましたが、簡単に表すと JavaScript を用いてサーバと非同期通信を行う手法で、 Ajax を用いることでWebページの内容をリロードなしで変更することができます。 ローカル環境で実装してみる まずは、ロジック理解のために通信先をローカルファイルにして実装してみます。 index3.html <!doctype html> <head> <meta charset="utf-8"> <title>Ajaxを利用してローカルの外部ファイルを読み込む</title> <link href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript" ></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js" type="text/javascript"></script> <script type="text/javascript"> $( function() { $( '#ajax-button' ) .click( function() { $.ajax( { //URL指定 url: 'sample.json', //データ形式指定 dataType : 'json', //通信に成功した場合の処理 success: function( data ) { var message = jsonParser(data); $( '#sample-text' ).html( message ); $( '#sample-text' ).html( obj.code ); $( '#sample-result' ).html( '<hr/><font color="blue">読み込み成功</font><hr/>' ); }, //通信に失敗した場合の処理 error: function( data ) { $( '#sample-result' ).html( '<font color="red">読み込みNG</font>' ); } } ); } ); $('#clear').click(function(){ $( '#sample-text' ).html(''); $( '#sample-result' ).html(''); }); } ); function jsonParser(data) { var message = data.code; message = message + '<br/>'; message = message + data.message; return message; } </script> </head> <body> <h3>Ajaxを利用してjson形式のファイルを読み込みパースする</h3> <p> <input type="button" id="ajax-button" value="読み込む"/> <input type="button" id="clear" value="clear" onclick="OnButtonClick"/> <br/> </p> <div id="sample-result"></div> <div id="sample-text"></div> </body> </html> 以下が今回読み込む sample.json です。 { "code" : "100", "message" : "メッセージ" } Webブラウザ で表示したのち、 読み込む ボタンを押すことによって json ファイルの中身が表示されました。 index3.html Ajax で外部 API へ通信する 以下のコードで外部の API へアクセスすることができます。 今回使用している API は、地域毎の天気予報を Json 形式で返す API です。 無料で会員登録無しで使うことができます。 $( function() { $( '#ajax-button' ) .click( function() { $.ajax( { //天気予報をJson形式で返すAPI url: 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400040',       //通信方法 type:'GET',       //データ形式を指定 dataType : 'json', //通信に成功した場合の処理 }).done(function(data){ alert("成功!"); $( '#sample-text' ).html( data.link ); //通信エラーになった場合の処理 }).fail(function(data){ alert("失敗!"); }); }); }); idが sample-text に Json ファイルの link を表示しています。 おわりに 今回は Ajax について基礎的な学習を行いました。 実践で使うことによってより理解が深まりますので、今回は手間を省くために会員登録の必要のない天気予報の API を利用しましたが、 次は使ってみたい外部の API を探し何か作ってみようと思います。 参考にした記事 http://javatechnology.net/ajax/biginer-start-up/ javatechnology.net エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに こんにちは!今回は大阪オフィスで開催された5月ビアバッシュのご紹介です。 令和一発目のビアバッシュは「テーマなし」にして、各々が自由に発表できる形式にしました。 それでは発表内容の一部をダイジェストでお送りいたします。 はじめに ビアバッシュ専用スマホアプリ ITエンジニアは学習しないと死んでしまう生き物 PHPerKaigi2019上映会振り返り 小さいことから始める改善 おわりに ビアバッシュ専用 スマホ アプリ 大阪ではビアバッシュのマンネリ化により、参加者や発表者が固定化するなどの課題を抱えています。 ビアバッシュをもっと楽しむための施策として、リアルタイムに発表にフィードバックできるアプリが登場しました! アプリに「発表内容」を登録しておくと、参加者はアプリを通じて発表内容にコメントやスタンプが送信できます。 このアプリを通じて、ベテランエンジニアだけでなく新人さんも気軽にビアバッシュに参加できるようになればいいですね~ ITエンジニアは学習しないと死んでしまう生き物 弊社エンジニアの"技術力向上"施策のお話です。 我々の業界ではエンジニアは常に技術力を磨かなければいけません。とは言え、やはりモチベーション維持が大変です。。 そんな中、 ラク スでは「学びをアウトプットする場の提供」に力を入れています! 特に最近では、社外向けに自社で Meetup を開催する、外部イベントへ 参加&登壇 するなどの活動を精力的に行っています。 エンジニアがより成長するためにも、今後も様々な施策を実施していきたいですね~ PHPerKaigi2019上映会振り返り PHPerの方にはお馴染み「PHPerKaigi」の上映会を実施したお話です。 本家PHPerKaigiの様子は fortee に動画コンテンツがまとまっているので上映しやすいですね~。 上映会後に発表内容についてみんなで議論することで新たな理解や関連知識を得ることができます。 "良い"技術イベントはみんなでシェアできるといいですね。 小さいことから始める改善 弊社エンジニアによる"改善のしかた"のお話です。 弊社に限らず、どの業界でも「改善」は大事です。一言に「改善」と言っても業務フローの見直しや特定作業の自動化など、挙げればいろいろありそうです。 しかし、まずは「記録する」ことが改善の第1歩。記録することで現状を把握し、チームで相談し合いながらより良くする方法を探すことができます。 今まで行ってきたタスクを記録し、 ECRSの法則 を使って不要なタスクの排除や類似タスクは結合していくといらないことに頭を使わなくてよくなりますb 筆者は ECRSの法則 は知らなかったのでこれを機に勉強してみたいです"φ(゚□゚ (゚□゚ )φ" メモメモ おわりに ビアバッシュも毎回いろんな発表が聞けて楽しいです。 参加してみて「なるほど」と思うことが多いので、個人的な勉強ネタが増えていきます(ただし、消化するのが大変です。。) ぜひ来月も期待して参加します~
アバター
id:radiocat です。毎月お楽しみのエンジニアもくもく勉強会のお知らせです。今回は6/13(木)に開催予定です。 rakus.connpass.com 5月のレポート 前回も様々な技術分野に取り組んでいる方々が参加されました。 PHP 、 Python 、Docker、Vue.jsといったキーワードが複数登場しています。 ブログを書いている人も多く、参加された皆さんの活動の一端を知ることができてエンジニアとして参考になります。また、プログラミングなどの作業の傍らで技術書籍を読んで参考にしている人も多くいらっしゃいました。社内で定期購読している技術雑誌がいくつかあるので、次回は会場内に置いてお読み頂けるようにしたいと考えています。必要に応じて学習の参考にして頂ければと思います。 会場の真ん中に置いてあるお菓子が好評なので引き続きご提供しています。帰宅前に軽くお菓子をつまみながら、もくもくして頂ければと思います。 今月も皆様のご参加をお待ちしております。 6/26(水)にはMeetupも開催予定です。 rakus.connpass.com こちらは参加だけでなくLTも募集しています。残り1枠となっていますので発表してみたいという方はお急ぎください。一般参加枠も募集開始2日目で50%を超えている状況です。ご興味のある方はお早めにご登録ください。もくもく勉強会と合わせてエンジニアの皆様のご参加をお待ちしております。
アバター
最近 RAKUS Meetup 関連の宣伝ばかりしている鈴木( @moomooya )です。今回は ラク ス開発部で実施している取り組みについて複数回にわたって紹介していければと思います。 ラク スの開発部ではこれまで社内で利用していなかった技術要素を自社の開発に適合するか検証し、ビジネス要求に対して迅速に応えられるようにそなえる 「 開 ( か ) 発の 未 ( み ) 来に 先 ( せん ) 手をうつプロジェクト(通称:かみせんプロジェクト)」 というプロジェクトがあります。こちらのプロジェクトの成果について定期的に紹介していきたいと思います。 連載目次 今後投稿される記事にリンクを貼っていきます。 『全文検索 〜 Elasticsearchとデータ匿名化手法』 ←今読んでいる記事 『全文検索の探求 Elasticsearch(1) 』: プロジェクト方針およびElasticsearch概要 大量データを検索するサービスでElasticsearchはRDBの代替候補になりうるか?(Elasticsearch vs pg_bigm)』 データ匿名化 第1回:匿名化された個人情報とは何なのか データ匿名化 第2回:個人情報は匿名化しても意味がないのではないか? データ匿名化 第3回:個人情報を匿名化するプロセス データ匿名化 第4回:匿名化のために行うデータ項目の一般化とは データ匿名化 第5回:データ匿名化の指標 データ匿名化 第6回:実際の匿名化 かみせんプロジェクトでは各チームから有志を募り、先述の課題解決を行う開発部横断プロジェクトとして2017年から運営されています。もちろん業務時間外での取り組み ではなく 、業務時間内での取り組みです(開発部の事業計画にもちゃんと記載されています)。 プロジェクト発足の理由 弊社も長くサービスを提供していますが、長く続くサービスにありがちなのが技術的な陳腐化。ありがたいことに商業的に成功を収めていますが、それゆえになおさら大きな変化を加えにくい状況になりつつあります。 とはいえ年々生産性の高い フレームワーク やライブラリが出てくる中で、変化を避け続けていると競合他社からの追い上げに負けてしまいかねません。5年後、10年後にも優位性を保つためには今後どういったものを取り入れるべきなのかを模索する必要があるという判断により、かみせんプロジェクトが発足することになりました。 なお、かみせんプロジェクトについては以前に取材されたこちらの記事もご参照ください。 マイクロサービスへの挑戦、ラクスが考える技術的負債を返済する最適なタイミング - Qiita:Zine 今期の取り組み かみせんプロジェクトでは一定期間ごとにテーマを変えて検証を進めていますが、今期2019年度上期は「 検索エンジン を用いた 全文検索 」をテーマに進めています。 検索エンジン としてはElasticsearchをターゲットに検証を進めています。Elasticsearch自体は2014年ごろから普及が進んでいましたが、弊社では活用ノウハウを貯めることができていませんでした。 スケーラブルな検索の仕組みは今後データ化される要素が増えて検索対象が大規模化していった際に必要になるものとして長期的な課題となっています。なのでまずは弊社で活用できそうな用途の検証が優先ですが、コンテナベースの クラスタ でスケールが必要になった時の運用ノウハウ蓄積も行なっていこうと考えています。 Elasticsearchは 全文検索 以外にも、Elastic Stack(以前はELK Stackと呼ばれていました)で知られるように分散システムのログ収集、分析、可視化基盤として利用できることや、マッチング度合いをみることができる特徴から今後のサービス展開において応用できる範囲は広いだろうと考えています。 併せて検索の際に必要がないデータや分析に必要ない機微情報を排除し、無用なリスクを低減するためにデータを匿名化する手法も副次的なテーマとして今期の取り組みに含めています。 データがどの程度匿名化されているかを数値化する手法や、データを匿名化するための一般化手法のノウハウを蓄積し、今後 ビッグデータ を利活用する際にもデータを適切に扱えるようになることを期待しています。 今後、定期的に記事を投稿していきますのでよろしくお願いします。 連載目次 今後投稿される記事にリンクを貼っていきます。 『全文検索 〜 Elasticsearchとデータ匿名化手法』 ←今読んでいる記事 『全文検索の探求 Elasticsearch(1) 』: プロジェクト方針およびElasticsearch概要 大量データを検索するサービスでElasticsearchはRDBの代替候補になりうるか?(Elasticsearch vs pg_bigm)』 データ匿名化 第1回:匿名化された個人情報とは何なのか データ匿名化 第2回:個人情報は匿名化しても意味がないのではないか? データ匿名化 第3回:個人情報を匿名化するプロセス データ匿名化 第4回:匿名化のために行うデータ項目の一般化とは データ匿名化 第5回:データ匿名化の指標 データ匿名化 第6回:実際の匿名化
アバター
はじめに こんにちは 入社2年目のEngawaです。タイトルに記載の通り5/18(土)に開催された JJUG CCC 2019 Springに参加してきました。 様々なセッションを見てきましたがその中でも特に印象に残ったものを紹介したいと思います。 http://www.java-users.jp/ccc2019spring/#/ www.java-users.jp ちなみに今回の JJUG には ラク ス社員も登壇しました!! 発表資料は下記からご確認ください。 tech-blog.rakus.co.jp tech-blog.rakus.co.jp 印象に残ったセッション テストエンジニアが教える  JUnit を書き始める前に考えるべきテスト JUnit の書き方についてではなくテストの目的は何か、なぜ早期のテストをするのかなどのテストコード作成の前に考えることについてのセッションでした。 提示された例題からどのようなテストを行うのか実際に考え、それをほかの方と共有することも行いました。大体似たり寄ったりな部分はあったのですが、細かな部分で目の付け所が違い、自分では思いつかないようなテストケースもありました。 テストケースを考える際はどこのテストを行うのか、なぜ行うのかを考えるのは当然だと思っていたのですが、それがどれくらい重要なことなのかを改めて実感しました。 今日から始めるカジュアルな ソースコード 解析 JavaParserという Java の 構文解析 ツールを使って、 ソースコード 解析の入門的な内容から、簡単な実用例までご紹介していくセッションでした。 構文解析 はいままで行ったことがなく、なんとなく敷居が高そうだなくらいの認識でしたが、そこまで難しくないのではないかと印象を受けたので手を出してみるいい機会になったかもしれません。 終わりに 今回初めて JJUG に参加しました。所々理解できなかったこともあり、自身の知識の乏しさを痛感させられました。 これを機にどのような技術が流行っているのかを把握し、今後のために学習を行っていこうと思います。
アバター
RAKUS Meetup のロゴ こんにちは、鈴木です。先日 RAKUS Meetup Tokyo #3 を開催いたしましたので、そちらのイベントレポートを投稿します。 当日の様子 発表の紹介 オブジェクトストレージ導入にあたり、ネットワークエンジニア観点で工夫した事、苦労した事。 売れてる SaaS へのオブジェクトストレージ導入にまつわる泥臭い話 懇親会 次回開催について 当日の様子 RAKUS Meetup Tokyo #3 会場の様子 今回は弊社本社オフィスの セミ ナールームでの開催でした。 当日は雨も降る 悪天候 の中ご参加いただきありがとうございました。RAKUS Meetup Tokyoは毎回雨が降っている気がします。次回は晴れて欲しいですね。 発表の紹介 オブジェクトストレージ導入にあたり、ネットワークエンジニア観点で工夫した事、苦労した事。 弊社インフラエンジニアの永易の発表です。 楽楽精算 にオブジェクトストレージを導入するにあたり考慮した内容を、情報セキュリティの3要素(機密性、完全性、可用性)に沿って発表しました。 プロダクト選定 ハードウェア構成 レプリケーション 設定 バージョニング設定 といった観点について発表しました。 売れてる SaaS へのオブジェクトストレージ導入にまつわる泥臭い話 弊社エンジニアの西角の発表です。 オブジェクトストレージの導入移行時に注意したことや、発生したトラブルについて発表しました。この発表は 先日のJJUG で発表した内容の再演+αになっています。 ファイルストレージをオブジェクトストレージにした際の実装上の影響範囲 20日 かけてデータ移行 移行後に発生したトラブル メンテナンス時間が約90%削減 といった観点について発表しました。 懇親会 お約束の Sushi と Pizza と Beer に加えて RED BULL を用意しました 次回開催について 次回の東京での開催は8月に 「納涼肝試し! WEBサービス 運用の怖い話」 をテーマに開催予定です。 今月6月の後半には募集を開始できると思います。 Connpassのグループ に入っていただけると通知が飛びますのでそちらもよろしくおねがいします。
アバター
はじめに こんにちは、新卒3年目エンジニアのkasuke18です。 私は昨年度の1年間、ビアバッシュ運営委員の一員として抜擢され、活動していました。 運営する中で見つかったとある課題に対して、Webアプリを導入することで カイゼン できそうだということになり、せっかくなのでビアバッシュ運営委員でWebアプリを作ることになりました。 現在その開発の真っ最中ですが、振り返ってみて得られた気付きをご紹介しようと思います。 はじめに やってみての気づき 一人で学習するよりも効率がよい わからないことは全員で考える 作業時間を作るのが大変 まとめ やってみての気づき 一人で学習するよりも効率がよい エンジニアとして自己学習は大切です。とはいえモチベーション維持が難しく、特に新しい技術を学ぶ場合は、一人では資料を見て手を動かすのが限界でマンネリ化してしまうことが多いです。その点、チームで開発することによって相互にレビューできるので、フィードバックをしたりされたりで、一人でやっていては気づけないことにも気づけます。そこからさらに個人的に気になったところを追加で学習することもあります。   わからないことは全員で考える チームメンバー内に詳しい人がおらず、若手メンバーのみで開発しているため、わからないことを相談しようにも全員わからないという場面があります。そのようなときは全員で ベストプラクティスは何だろう? などと考えながら進めています。三人寄れば 文殊 の知恵、というほどうまくいかなくとも全員で考えた結果なので納得感を持って進められます。 作業時間を作るのが大変 手元に開発環境がなければ確認できないので、まとまった時間を作って自宅で作業(実装・レビュー)することが多くなります。とはいえ、他にもやりたいことがあるので、基本的には週末以外ではまとまった時間が取れません。この課題はチームメンバー内でも認識しており、 もくもく勉強会 などの集まれる時間を作ってモブプロ的に開発をすることで、差し戻しの手間を減らし、効率的に進められるように対策しています。 また、個人でも通勤時間中にコードを見るだけなら スマートフォン でもできるので、コードレビューだけやることにしています。先にできることはやっておいて、週末は動作確認と自分の実装に集中して取り組むというようにしています。 まとめ この記事を書くにあたって、個人的に振り返ってみました。 今回の開発で採用した新しい技術は、個人的には一人で学習するにはハードルが高く、おそらく中途半端に学習するだけで終わってしまうことになってしまいそうですが、チームで開発することでそのような状況を回避できました。 毎回このような機会があるわけではないので、次に未経験の技術を学習する際は 勉強会 に参加するなどして、意見交換ができる場に身を置くことを選択肢として考えようと思います。
アバター
こんにちわ @kawanamiyuu です。先日 ブログでお知らせ しました通り、5/18 (土) に開催された JJUG CCC 2019 Spring で登壇してきました。 もうひとりの登壇者である西角さんの登壇レポートはこちら↓ tech-blog.rakus.co.jp 登壇資料 speakerdeck.com 登壇に対する反応 #ccc_i2b hashtag on Twitter ありがたいことに満席でした! 立ち見出てます!! #ccc_i2b #jjug_ccc — yaaka (@yaaka4) 2019年5月18日 人が多すぎてびっくり #ccc_i2b — tea (@tethon) 2019年5月18日 セッションの冒頭で ArchUnit を知っているか問いかけてみたところ、ほぼ全員の方が ArchUnit を知らなかったようでした。 ArchUnit。 初めて聞いた。 — すめらぎ (@sumeragizzz) 2019年5月18日 アーキテクチャ の品質維持関する悩み、ArchUnit の魅力、テストコードのア イデア や事例を共有できる絶好の機会となりました。 アーキテクトの悩み めっちゃわかる 初期の設計がいつの間にか守られなくなる 新規メンバーへの周知ができていない レビュー負担 #ccc_i2b — hituzi3939 (@hituzi3939) 2019年5月18日 commonがいつの間にかcommonでなくなるのは、あるある過ぎる #ccc_i2b #jjug_ccc — yaaka (@yaaka4) 2019年5月18日 ArchUnit、 アーキテクチャ だけじゃなくてアプリケーション・チーム固有のルールも適応度関数化できてだいぶよさそう #ccc_i2b — enk (@enk_enk) 2019年5月18日 普段、ドキュメントに書いてるような開発標準をテストコードで表現して自動チェックできる感じっぽくてよさそう > ArchUnit #jjuc_ccc #ccc_i2b — kntmr (@knt_mr) 2019年5月18日 ArchUnit をぜひプロダクトで活用していただきたい! ArchUnit これは使えそう。 — かわぬん (@chronos2074) 2019年5月18日 セッションは聞いてないんだけど、ArchUnit が良さそうだったなー。一度は評価してみたい。 — Hirotaka Ikoma (@hikoma) 2019年5月18日 さいごに (登壇資料の結びの言葉より) 自動テストで アーキテクチャ の品質を担保しつつ、プロダクト開発を通じて継続的に アーキテクチャ を磨いていくことができるとしたら... どうでしょうか。わくわくしないでしょうか? 😄
アバター
こんにちは。西角(west-c)です。 先日告知がありました通り 、5月18日(土)に開催された JJUG CCC 2019 Spring にて「売れてる SaaS へのオブジェクトストレージ導入にまつわる泥臭い話」というタイトルで登壇しました。 当日発表を見に来てくださった皆様、ありがとうございました。 発表資料 登壇レポート 今年でサービス開始10周年を迎える「 楽楽精算 」にオブジェクトストレージを導入したプロジェクトでの一部始終として、以下のようなお話をしました。 オブジェクトストレージ導入の要因となった楽楽精算が抱えていた課題 クラウド サービス( Amazon S3 など)ではなくオンプレミスのストレージを選択した理由 導入時にアプリケーションの設計面で意識した点 導入後に発生したトラブルから意識すべきだった点 アプリケーションの設計に着手したのはちょうど去年の今頃でしたが、今回の私達のようにオブジェクトストレージへファイルデータ移行を行った事例はあまり見当たらず、手探り状態で設計を進めていたと記憶しています。 今回の登壇が決まってから、同じような課題・悩みを抱える(または今後抱かれるかもしれない)方向けにできる限り生身の情報をお届けしたいと考え、準備を進めました。 拙い発表ではありましたが、発表を聞いてくださったり資料を見てくださった皆様にとって何かしらの知見が得られる内容になれば幸いです。 また、こちらは個人的な話ですが、私にとって今回が初めての外部技術イベントでの登壇でした。 緊張こそしましたが、大きな問題も起きず発表を終えることができて良かったです。 これも資料作成や発表練習に付き合っていただいたり当日応援に来てくれた弊社メンバーの協力のおかげです 🙇 一方で、登壇の場に慣れていないことによる反省点も多々感じましたので、今後もこういった場に参加することで腕を磨いていきたいと思いました!
アバター
こんにちは、MasaKuです。 先日、 PostgreSQL の運用知識学習として以下の書籍を読みました。 gihyo.jp 書籍内で紹介されていた「 パーティショニング 」について、公式ドキュメントに記載されている内容と照らし合わせて、どのようなケースであればパフォーマンスの向上が見込めるのかを確認してみようと思いました。 なお、PostgreSQL11のパーティショニングについては、弊社の アドベントカレンダー にも掲載されておりますので、あわせてご確認いただけると幸いです。 qiita.com テーブルのパーティショニングとは パーティショニングのメリット データの準備 実践 パーティションのキーを用いた検索の場合 全体検索の場合 パーティション分割のキー以外の検索の場合 おわりに 参考サイト テーブルのパーティショニングとは 1つのテーブルを複数のテーブルに分割して管理することをテーブルのパーティショニングといいます。 パーティショニングには以下の種類があります。 ショッピングサイトの購入履歴に関するデータ管理方法を例に説明したいと思います。 レンジ・パーティショニング 指定された範囲の値を基にデータを分散して配置する。 (例: 購入履歴テーブルを1ヶ月単位で分割) レンジ・パーティショニング リスト・パーティショニング テーブルのキーの値を基にデータを分散して配置する (例: 商品カテゴリIDによる分割) リスト・パーティショニング ハッシュ・パーティショニング( PostgreSQL 11 より) データの挿入時にカラムの ハッシュ値 を元に特定の パーティション にデータが偏らないように分散して配置する (例: レコードIDによる分散) ハッシュ・パーティショニング パーティショニングのメリット PostgreSQLの公式ドキュメント ではパーティショニングのメリットを以下のように説明されています 特定の条件下で問い合わせのパフォーマンスが劇的に向上することがあります。 特にテーブル内のアクセスが集中する行の殆どが単一または少数の パーティション に存在している場合がそうです。 パーティショニングはインデックスの先頭にある列の代わりになり、インデックスの大きさを小さくして、インデックスの頻繁に使われる部分がメモリに収まりやすくなるようにします。 問い合わせや更新が一つの パーティション の大部分にアクセスする場合、インデックスやランダムアクセスを使用してテーブル全体にまたがる読み取りをする代わりに、その パーティション への順次アクセスをすることでパフォーマンスを向上させることができます。 一括挿入や削除について、その要件を パーティション の設計に組み込んでいれば、それを パーティション の追加や削除で実現することが可能です。 ALTER TABLE DETACH PARTITIONを実行する、あるいは個々の パーティション を DROP TABLEで削除するのは、一括の操作をするよりも遥かに高速です。 これらのコマンドはまた、一括のDELETEで引き起こされるVACUUMのオーバーヘッドを完全に回避できます。 滅多に使用されないデータを安価で低速なストレージメディアに移行することができます。 今回は、1つ目の利点に着目して動作を確認してみたいと思います。 データの準備 検証のために以下のテーブルを作成しておきます。 -- 商品カテゴリテーブル CREATE TABLE categories( id SERIAL PRIMARY KEY, name TEXT UNIQUE ); -- 商品カテゴリテーブルのサンプルデータ INSERT INTO categories (name) VALUES ( ' 食品 ' ); INSERT INTO categories (name) VALUES ( ' 衣類 ' ); INSERT INTO categories (name) VALUES ( ' 本 ' ); INSERT INTO categories (name) VALUES ( ' コンピュータ ' ); -- 購入位履歴テーブル CREATE TABLE purchase( id SERIAL PRIMARY KEY, category_id INTEGER , name TEXT, date TIMESTAMP DEFAULT NOW()), FOREIGN KEY (category_id) REFERENCES categories(id) ); 購入履歴テーブルのテストデータは過去5年分で合計50万件とします。 -- 購入履歴テーブルのサンプルデータ INSERT INTO purchase (name, category_id, date ) SELECT ' test ' , TRUNC ((RANDOM() * 4 ):: NUMERIC, 0 ) + 1 , ' 2014-01-01 ' :: DATE + (RANDOM() * 1780 ):: INTEGER AS date FROM GENERATE_SERIES( 1 , 500000 ) ; パーティショニングで作成するテーブルについては後述します。 実践 文章内にもありますとおり、特定条件下とは「特にテーブル内のアクセスが集中する行の殆どが単一または少数の パーティション に存在している場合」です。 購入履歴を例にして考えてみたいと思います。 あるサービスでは、5年分の購入履歴を保管しているとします。 そのうち、直近1年の購入履歴からオススメ商品を提示する機能を実装する場合、購入履歴を一つのテーブルで管理するよりも、年単位で分割されたテーブルで管理しておくほうがパフォーマンスは向上するようです。 今回のケースでは date カラム をキーとするレンジ・ パーティション を行います。 CREATE TABLE purchase_range( id SERIAL, category_id INTEGER , name TEXT, date TIMESTAMP DEFAULT NOW(), FOREIGN KEY (category_id) REFERENCES categories(id) ) PARTITION BY RANGE ( date ); CREATE TABLE purchase_range_y2014 PARTITION OF purchase_range FOR VALUES FROM ( ' 2014-01-01 00:00:00 ' ) TO ( ' 2014-12-31 23:59:59 ' ); CREATE TABLE purchase_range_y2015 PARTITION OF purchase_range FOR VALUES FROM ( ' 2015-01-01 00:00:00 ' ) TO ( ' 2015-12-31 23:59:59 ' ); CREATE TABLE purchase_range_y2016 PARTITION OF purchase_range FOR VALUES FROM ( ' 2016-01-01 00:00:00 ' ) TO ( ' 2016-12-31 23:59:59 ' ); CREATE TABLE purchase_range_y2017 PARTITION OF purchase_range FOR VALUES FROM ( ' 2017-01-01 00:00:00 ' ) TO ( ' 2017-12-31 23:59:59 ' ); CREATE TABLE purchase_range_y2018 PARTITION OF purchase_range FOR VALUES FROM ( ' 2018-01-01 00:00:00 ' ) TO ( ' 2018-12-31 23:59:59 ' ); -- 購入履歴テーブルサンプルデータ(パーティション) INSERT INTO purchase_range (name, category_id, date ) SELECT ' test ' , TRUNC ((RANDOM() * 4 ):: NUMERIC, 0 ) + 1 AS category_id, ' 2014-01-01 ' :: DATE + (RANDOM() * 1780 ):: INTEGER AS date FROM GENERATE_SERIES( 1 , 500000 ) ; パーティション のキーを用いた検索の場合 まずは、2017年12月の購入履歴の件数を取得する SQL を実行した結果を見てみましょう。 -- 単一テーブルで管理されている場合 explain analyze select count (*) from purchase where date > ' 2017-12-01 ' and date < ' 2017-12-31 ' ; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (cost= 6114 . 90 .. 6114 . 91 rows = 1 width= 8 ) (actual time= 125 . 218 .. 125 . 218 rows = 1 loops= 1 ) -> Gather (cost= 6114 . 69 .. 6114 . 90 rows = 2 width= 8 ) (actual time= 120 . 538 .. 125 . 274 rows = 3 loops= 1 ) Workers Planned: 2 Workers Launched: 2 -> Partial Aggregate (cost= 5114 . 69 .. 5114 . 70 rows = 1 width= 8 ) (actual time= 96 . 651 .. 96 . 652 rows = 1 loops= 3 ) -> Parallel Seq Scan on purchase (cost= 0 . 00 .. 5108 . 41 rows = 2513 width= 0 ) (actual time= 0 . 036 .. 96 . 162 rows = 2053 loops= 3 ) Filter: (( date > ' 2017-12-01 00:00:00 ' ::timestamp without time zone) AND ( date < ' 2017-12-31 00:00:00 ' ::timestamp without time zone)) Rows Removed by Filter: 100529 Planning Time: 0 . 215 ms Execution Time: 125 . 323 ms -- パーティションで分割しているテーブルの場合 explain analyze select count (*) from purchase_range where date > ' 2017-12-01 ' and date < ' 2017-12-31 ' ; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost= 26 . 09 .. 26 . 10 rows = 1 width= 8 ) (actual time= 0 . 007 .. 0 . 007 rows = 1 loops= 1 ) -> Append (cost= 0 . 00 .. 26 . 07 rows = 5 width= 0 ) (actual time= 0 . 004 .. 0 . 004 rows = 0 loops= 1 ) -> Seq Scan on purchase_range_y2017 (cost= 0 . 00 .. 26 . 05 rows = 5 width= 0 ) (actual time= 0 . 003 .. 0 . 003 rows = 0 loops= 1 ) Filter: (( date > ' 2017-12-01 00:00:00 ' ::timestamp without time zone) AND ( date < ' 2017-12-31 00:00:00 ' ::timest amp without time zone)) Planning Time: 0 . 667 ms Execution Time: 0 . 034 ms 実行時間は パーティション で分割しているテーブルの方が短くなるという結果になりました。 日時で パーティション を分割しているため、対象外の期間のレコードにはアクセスされないためパフォーマンスが向上しました。 全体検索の場合 今度は、全データの件数を取得する場合を考慮してみました。 -- 単一テーブルで管理されている場合 explain analyze select count (*) from purchase; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (cost= 6789 . 38 .. 6789 . 39 rows = 1 width= 8 ) (actual time= 274 . 970 .. 274 . 970 rows = 1 loops= 1 ) -> Gather (cost= 6789 . 17 .. 6789 . 38 rows = 2 width= 8 ) (actual time= 273 . 169 .. 275 . 097 rows = 3 loops= 1 ) Workers Planned: 2 Workers Launched: 2 -> Partial Aggregate (cost= 5789 . 17 .. 5789 . 18 rows = 1 width= 8 ) (actual time= 252 . 091 .. 252 . 092 rows = 1 loops= 3 ) -> Parallel Seq Scan on purchase (cost= 0 . 00 .. 5268 . 33 rows = 208333 width= 0 ) (actual time= 0 . 016 .. 105 . 048 rows = 166667 loops= 3 ) Planning Time: 0 . 135 ms Execution Time: 275 . 149 ms -- パーティションで分割しているテーブルの場合 explain analyze select count (*) from purchase_parent; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (cost= 8690 . 90 .. 8690 . 91 rows = 1 width= 8 ) (actual time= 429 . 425 .. 429 . 425 rows = 1 loops= 1 ) -> Gather (cost= 8690 . 68 .. 8690 . 89 rows = 2 width= 8 ) (actual time= 429 . 415 .. 429 . 608 rows = 3 loops= 1 ) Workers Planned: 2 Workers Launched: 2 -> Partial Aggregate (cost= 7690 . 68 .. 7690 . 69 rows = 1 width= 8 ) (actual time= 406 . 901 .. 406 . 901 rows = 1 loops= 3 ) -> Parallel Append (cost= 0 . 00 .. 7169 . 85 rows = 208334 width= 0 ) (actual time= 0 . 018 .. 269 . 589 rows = 166667 loops= 3 ) -> Parallel Seq Scan on purchase_y2017 (cost= 0 . 00 .. 1259 . 81 rows = 60481 width= 0 ) (actual time= 0 . 015 .. 90 . 205 rows = 102817 loops= 1 ) -> Parallel Seq Scan on purchase_y2015 (cost= 0 . 00 .. 1259 . 19 rows = 60419 width= 0 ) (actual time= 0 . 017 .. 112 . 477 rows = 102713 loops= 1 ) -> Parallel Seq Scan on purchase_y2016 (cost= 0 . 00 .. 1257 . 65 rows = 60365 width= 0 ) (actual time= 0 . 016 .. 18 . 776 rows = 34207 loops= 3 ) -> Parallel Seq Scan on purchase_y2014 (cost= 0 . 00 .. 1255 . 53 rows = 60253 width= 0 ) (actual time= 0 . 014 .. 61 . 613 rows = 51215 loops= 2 ) -> Parallel Seq Scan on purchase_y2018 (cost= 0 . 00 .. 1096 . 00 rows = 52600 width= 0 ) (actual time= 0 . 019 .. 76 . 853 rows = 89420 loops= 1 ) Planning Time: 0 . 162 ms Execution Time: 429 . 668 ms ある意味予想通りでしたが、実行時間はパーティショニングしているテーブルのほうが長くなりました。 テーブルを分割しているために、本来一度で完了するシーケンシャルスキャンが パーティション の数だけ実行されるため、パフォーマンスが劣化したと思われます。 購入履歴を検索する、ということに主眼を置く場合は、運用方法次第ではパーティショニングが必ずしも適切ではない場合もあるので注意が必要です。 パーティション 分割のキー以外の検索の場合 最後に、 パーティション 分割に利用したキー以外のカラムを絞込み条件にした場合のパフォーマンスを確認してみます。 今回はカテゴリIDを対象にした検索を行ってみたいと思います。 -- 単一テーブルで管理されている場合 explain analyze delete from purchase where category_id = 1378 ; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Delete on purchase (cost= 0 . 00 .. 7031 . 81 rows = 1 width= 6 ) (actual time= 87 . 803 .. 87 . 803 rows = 0 loops= 1 ) -> Seq Scan on purchase (cost= 0 . 00 .. 7031 . 81 rows = 1 width= 6 ) (actual time= 87 . 801 .. 87 . 801 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 307745 Planning Time: 0 . 062 ms Execution Time: 87 . 829 ms -- パーティションで分割しているテーブルの場合 explain analyze delete from purchase_range where category_id = 1378 ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Delete on purchase_range (cost= 0 . 00 .. 7869 . 12 rows = 5 width= 6 ) (actual time= 103 . 825 .. 103 . 826 rows = 0 loops= 1 ) Delete on purchase_range_y2014 Delete on purchase_range_y2015 Delete on purchase_range_y2016 Delete on purchase_range_y2017 Delete on purchase_range_y2018 -> Seq Scan on purchase_range_y2014 (cost= 0 . 00 .. 1614 . 14 rows = 1 width= 6 ) (actual time= 22 . 576 .. 22 . 576 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 76811 -> Seq Scan on purchase_range_y2015 (cost= 0 . 00 .. 1612 . 55 rows = 1 width= 6 ) (actual time= 21 . 112 .. 21 . 112 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 76844 -> Seq Scan on purchase_range_y2016 (cost= 0 . 00 .. 1627 . 21 rows = 1 width= 6 ) (actual time= 20 . 850 .. 20 . 850 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 77537 -> Seq Scan on purchase_range_y2017 (cost= 0 . 00 .. 1603 . 49 rows = 1 width= 6 ) (actual time= 21 . 146 .. 21 . 146 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 76279 -> Seq Scan on purchase_range_y2018 (cost= 0 . 00 .. 1411 . 74 rows = 1 width= 6 ) (actual time= 18 . 105 .. 18 . 106 rows = 0 loops= 1 ) Filter: (category_id = 1378 ) Rows Removed by Filter: 67099 Planning Time: 0 . 376 ms Execution Time: 103 . 901 ms 多少の差があるもののそこまで大きな差がないという、少し意外な結果となりました。 というのも、今回作成したサンプルデータは日付でパーティショニングしているため、カテゴリIDで絞り込んだ場合は分散配置しているテーブルすべてをチェックしなければならなくなります。 そのため、先ほどの全体検索と同程度のパフォーマンスになると思っていました。 パーティション で分割されているテーブルの数や、1テーブルに格納されているレコードの量によって差が出るのではないでしょうか。 おわりに パーティショニングといっても、データ管理の 銀の弾丸 というものではなく、場合によってはパフォーマンスが劣化する場合があることがわかりました。 今回はレンジ パーティション を例にしましたが、実際のサービスがどのように運用されていくかを考慮することで、どのように パーティション を分割すべきかが見えてくるのではないでしょうか。 (もしくは、 パーティション 分割する必要が無いことも) その他にも、継承パーティショニングの検証や、高負荷状態でのパフォーマンスなど、検証してみたいことがありましたが、その辺はまた別の機会にしたいと思います。 参考サイト [改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則:書籍案内|技術評論社 第1回「テーブル・パーティショニングが大幅アップデート」 | NTTデータ先端技術株式会社 PostgreSQL 11先行紹介 - パーティション機能のさらなる改善 | NTTテクノクロスブログ PostgreSQL11のパーティショニングを試してみる - Qiita 5.10. テーブルのパーティショニング エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに 最近、 オライリー から出版されている「ヘルシー プログラマ 」という書籍を読みました。 エンジニア目線で健康について書かれているのですが、面白い内容だったので紹介してみたいと思います。 www.oreilly.co.jp はじめに 概要 なぜ読もうと思ったのか? 面白いと思ったポイント まとめ 概要 長時間座ったまま仕事を続ける プログラマ の悩みである、腰痛、手首の痛み、目の痛みや頭痛といった健康問題に対して、食生活や生活習慣を改善する方法や簡単なエクササイズを紹介しているエンジニア向けの書籍になります。 なぜ読もうと思ったのか? 連休の間に技術書を1冊は読もうと思っていた 本屋へ探しに行ったときに技術書のコーナーでたまたま見つけたからです。 面白そうだと思ったので購入してみました。 最近、健康意識が高めなので少し読んでみて面白かった。 自炊をし始めて3年目に突入し、普段から食習慣には気をつかっています。 広く浅く調べたりしていますが、もう少し知識が欲しいと思っていました。 健康や栄養学に興味があることも大きい理由です。 面白いと思ったポイント エンジニアにウケそうな表現が多くてじわじわくる 健康状態を改善することを リファクタリング と表現されている アジャイル な方法論で書かれている 「体重計はサーバのメモリをモニタリングするのと同じように、健康をモニタリングするためのツール」 説明が科学的であること 学会誌から引用されていたり、数値などによる科学的な裏付けのある説明になっているので説得力がありました。 プログラマ 視点で書かれていることもあり、ロジカルな内容でした。 頭痛、眼精 疲労 、腰痛、手首痛への対策 それぞれ、デスクワークによって引き起こされる原因が科学的に書かれていて、その対策や、エクササイズについて書かれています。 眼精 疲労 やそれによる頭痛は特に悩みなので、以下のような対策を意識してやってみようかなと思いました。 「頭痛は生活を脅かすほどのものでなくても、生産性を下げてしまう」と書かれていましたが、そのとおりだと思います。 こまめに瞬きする 目の運動をする(20分に1回、6メートル先を20秒見つめる) 休憩を頻繁に取る(目を休めるミニ休憩を増やす) メガネを外す(意外と大事!) カフェインは摂りすぎない(頭痛を誘発する、一時的に解消する効果もあるので注意) 水を飲む(1日2リットル) まとめ 健康には気をつけたいけど、何をしたら良いかわからないエンジニアには良い書籍なのではないかと思いました。 新卒3年目になり、健康であることは自分のパフォーマンスに繋がってくるなと日々感じています。 運動しないといけないなーという気持ちになり、生活習慣を改善しようとするきっかけにはなったと思います。 ちょうど健康診断のシーズンでもあるので、 リファクタリング を始めるきっかけの参考になれば幸いです。
アバター
はじめに GAS(Google Apps Script)とは 今回やること GASの実行結果を書き込むSpreadSheetの作成 GASの作成 POSTする設定 補足:承認を求められたら curlからPOSTする おわりに はじめに kuwa_38です。この記事では Google Apple Scriptとして作成した スクリプト を curl コマンドから実行する方法を紹介します。 GAS( Google Apps Script)とは 以前このブログで書かれていた記事の中に分かりやすい説明があったので引用します。 「 Google の各種アプリ( Google スプレッドシート / Google ドキュメントなど)をアプリ内ではなく外から操作できるJSライクな プログラミング言語 」です。 エクセルに対する VBA の関係と一緒です。 tech-blog.rakus.co.jp 上の記事は入門として スクリプト エディタ上から作成した スクリプト を実行しています。本記事では スクリプト エディタ上からでなく、外部( curl コマンド)から実行する方法の紹介となります。 今回やること curl コマンドからGASを実行するための大まかな手順は以下です。 GASの実行結果を書き込むSpreadSheetの作成 GASの作成 POSTする設定 curl からPOSTする GASの実行結果を書き込むSpreadSheetの作成 今回は以下のようなシートを作成し、果物(fruit)と値段(price)を末尾に追記します。 書き込むSpreadSheet GASの作成 以下を スクリプト エディタに記載します。 /** * POSTされた時に実行されるメソッド. * 行の最後に受け取った値を挿入する * @param e 下記のJSONを想定 * fruit:フルーツ名 * price:価格 * @return なし */ function doPost(e) { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName( 'シート名' ); var PostData = JSON.parse(e.postData.contents); // 行の最後に値を追加 sheet.appendRow( [ PostData.fruit, PostData.price ] ); } 参考: qiita.com POSTする設定 POSTする前に作成した スクリプト にアクセスできるように設定します。 公開 > ウェブアプリケーション として導入 スクリプト 許可1 次のユーザとしてアプリケーションを実行:自分 アプリケーションにアクセスできるユーザ:全員(匿名ユーザを含む) スクリプト 許可2 更新ボタンを押すと、接続するためのURLが作成されます curl で接続する際に使用するのでコピーしておくと良いです スクリプト 許可3 参考: yamap55.hatenablog.com 補足:承認を求められたら 承認を求められた場合は下記を参考に承認してください。 tonari-it.com curl からPOSTする 以下の curl を実行し、POSTします。 curl -X POST -H "Content-Type: application/json" -d '{"fruit":"peach", "price":"650" }' -L https://script.google.com/macros/s/xxxx/exec スクリプト 実行結果 おわりに この記事では curl コマンドを使ってPOSTし、GAS( Google Apple Script)を実行する方法を紹介しました。今回は curl コマンドを直打ちでしたが、自作アプリなどからPOSTする仕組みにしておけば、SpreadSheetへの操作をより手軽にできるようになるかと思います(何か作りたいなと思案中)。 気になった方はぜひ試してみてください。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちわ @kawanamiyuu です。来週末に開催される、日本最大の Java コミュニティイベント JJUG CCC 2019 Spring に ラク スのエンジニアが 2 名登壇しますのでお知らせします。 イベント概要 日時:2019 年 5 月 18 日 (土) 会場: ベルサール 新宿グランドコンファレンスセンター 公式 HP: http://www.java-users.jp/ccc2019spring/ ハッシュタグ : #jjug_ccc www.java-users.jp goo.gl 登壇セッション セッション一覧はコチラ →  http://www.java-users.jp/ccc2019spring/#/sessions 1.売れてる SaaS へのオブジェクトストレージ導入にまつわる泥臭い話 登壇者:西角知佳(東京拠点エンジニア) セッション詳細 <概要> 「楽楽精算」 は株式会社 ラク スが提供する経費精算 クラウド サービスです。市場の成長や 働き方改革 といった社会情勢とともにサービスも成長を続けています。その一方で、売れているサービスであるがゆえに蓄積した技術的負債やビジネスのスケールに伴う運用課題もまた抱えています。 その課題の1つとして、増え続ける顧客データのバックアップ肥大化およびバックアップ時間増大という課題が深刻化していました。リリースメンテナンス時間への影響も無視できなくなってきたことから、 Amazon S3 ...ではなく、 Amazon S3 互換のプライベートオブジェクトストレージへのデータ移行に踏み切りました。 オブジェクトストレージ導入にあたりどのように技術選択をし、どのように大切な顧客データを安全確実に移行したのか。また、リリース後に発生した問題にどのように対処したのか。サービスローンチから10年が経過し、オンプレミス、某 Java フレームワーク と決して今をときめく技術スタックで構成されたサービスではない楽楽精算にとっての技術的なチャレンジについて、成長を続けるサービスが必ず通りうるであろう現実的で泥臭いお話を具体的に発表します。 翌週に開催予定の RAKUS Meetup Tokyo #3 のリードセッションを JJUG CCC 2019 Spring という特別な場所からひと足早くお届けします。 2.ArchUnit で Java / Kotlin アプリケーションの アーキテクチャ を CI する 登壇者:かわなみゆう(大阪拠点エンジニア) セッション詳細 <概要> ArchUnit とは一言でいうと、 Java / Kotlin アプリケーションのパッケージやクラスの依存関係や、アプリケーション固有の実装ルールを JUnit のテストコードして表現しテストできるテスト フレームワーク です。 我々にとって ArchUnit はなにが嬉しいのか。ArchUnit でできることは人間によるコードレビューや静的解析によってもチェックできそうに思えます。 この発表では、実際に私たちのプロダクトの CI に組み込まれているテストコードの実例と合わせて、アーキテクトの観点、開発チームの観点から ArchUnit のウレシみについてお話します。 最後に 今回が ラク スとして初めて Java のイベントへの登壇です。そして、東京拠点エンジニアからの社外イベント登壇も初です。今年度も ラク スはイベント登壇への取り組みを更に加速させていきます。 最後になりましたが、当日、セッションでお会いできるのを楽しみにしています!
アバター
id:radiocat です。大阪でエンジニアもくもく勉強会の運営をしています。令和も継続して開催しますのでぜひご参加ください。 rakus.connpass.com 初開催から予想より多くの方々に参加して頂き、今回はありがたいことに早くも定員に達してしまいましたので増枠しています。様々なエンジニアの方にお会いできて、一緒に参加する弊社の社員も楽しませて頂いています。 4月のレポート 平成最後のエンジニアもくもく勉強会の様子を少しだけご紹介します。 参加頂いた方々はご覧のようなテーマで自習されていたようです。 付箋の内容は自己紹介も兼ねて簡単に共有して頂くようにしています。 PHP 関係のテーマが比較的多かった印象で、参加者同士の情報交換なども行われていました。他にも Rails やJS、 Java を扱う内容もあって、自分の好きなテーマで自由に取り組んで頂くことができます。 エンジニア経歴も、お聞きする限り様々で、若手からベテラン、そして学生のかたも参加されています。弊社の運営も次回から若手メンバーにも手伝ってもらう予定で、幅広くサポートしていければと思います。 終業後の小腹が空く時間帯ですので、真ん中のテーブルでお菓子をご自由にお取り頂けるようになっています。気軽に立ち寄れて、エンジニアが楽しめる場づくりを目指しています。一緒に楽しんで頂けるエンジニアの皆様のご参加をお待ちしております。
アバター
はじめに こんにちは。令和最初の記事は sts -250rrからお届けします。 私ごとですが、プロジェクトが変わり5月から アジャイル 開発を行うことになりました。 アジャイル 開発の中でも スクラム をやるとのことだったので、GWの期間を利用して、SCRUM BOOT CAMP の本を読んでみました。 今回は自身の頭の中の整理を記事に残しておこうと思います。 実際にやってみるのはこれからになりますので、間違いもあるかと思いますがご容赦ください。 はじめに アジャイル開発とは スクラムとは? スクラムの特徴 スクラムの全体像 スクラムでの開発チームの役割 開発チームの進め方 スプリントの進め方 リリース判断可能 スプリントレビュー スプリントレトロスペクティブ(振り返り) 終わりに 参考 アジャイル 開発とは アジャイル 開発では、「事前にすべてを正確に予測し、計画することはできない」という前提のもと以下のような進め方を行います。 関係者は目的達成のためにお互いに協力しあいながら進める 利用者の反応や関係者からのフィードバックを継続的に得ながら、計画を調整する。 一度にまとめてではなく、少しずつくくる。そして実際に出来上がったものが求めているものであるかを頻繁に確認する。 アジャイル ではおおよその全体像は明らかにした上で、重要なものやリスクの高いものを優先し、重要度の低いものは後に回すことで、要求の分析や設計に対して必要以上の時間をかけないことで開発スピードを上げていく手法です。 ユーザが求めているものを素早く提供するようなサービスに向いている手法かと思います。 スクラム とは? スクラム は アジャイル 開発の中の手法の1つで、関係者の進む方向を常に調整しながら目的を達成するため、 作業、会議、成果物を定めた 手法です。 あくまで仕事の進め方にフォーカスをしたものであるため、細かなルール(コーディング規約やテストの方法など)は自分たちで決める必要があります。 書籍に記載の スクラム の特徴を記載します。 スクラム の特徴 要求を常に順番に並び替え、その順にプロダクトを作ることで成果を最大化する 実現されることの価値やリスク、必要性を基準にする 固定の短い時間に区切って作業を進める 現時点の進捗や問題点を常に明らかにする 定期的に今進めているものが正しいのか、進め方に誤りはないのかの確認を行う 進め方に問題があったり、もっと良い方法があった場合にはやり方を変更する スクラム の全体像 SCRUM BOOT CAMP の著者でもある @ryuzee さんの図を見ていただくのが良いかと思います。 www.ryuzee.com この図を見て感じたことは、1スプリントでプロダクトオーナーのレビューを受ける必要があるため、どの程度の作業ができるのかをよく把握しておかなければならないという点です。 こうなってくると、1スプリントのなかでどこまでのことができるかを決めるスプリントプランニングや、今どこまでできているかを確認するデイリー スクラム が重要になってくることもうなずけます。 スクラム での開発チームの役割 私は開発チームとして スクラム に関わることになるので、開発チームの役割を掘り下げていきます。 開発チームの役割は以下の点です。 リリース判断ができるプロダクトを作る 6名(±3名)で構成する 全員揃えばプロダクトを作れる 上下関係はない また、開発チームは要求の分析・設計・コーディング・サーバの構築・ドキュメントの作成といった システム開発 に必要なことが全てできる必要があります。 これは各作業に個人を割り当てるというものではなく、個人が複数のことができるようになるということです。 開発チームの進め方 開発チームはプロダクトの作っていくためにスプリントを進めていくわけですが、1スプリントでどこまで作業を行うのかを決める スプリントプランニング を実施します。 スプリントプランニングは、プロダクトオーナーを含めて何が欲しいのか、開発チームではどこまでできるのかをすり合わせる第1部。 第1部で決まったことをどのように実現するのかを開発チーム内ですり合わせる第2部で構成されています。 ここで決定したことを スプリント バックログ という形でタスクの一覧を用意し、スプリントの中で実施していきます。 スプリントの進め方 スプリントを行なっていく上でのポイントですが、開発チームはスプリントプランニングの中で合意した内容を達成することに全力を尽くす必要がありますが、全てを完了することを約束するものではないということです。 全てを完了することを目的に作業をしてしまうと、不測の事態が発生したり、必要な作業を飛ばしてしまったりといった問題が発生し、「本当に欲しいもの」が作れない可能性があるためです。 この場合はプロダクトオーナーと相談し、プロダクト バックログ のリストを見直したりすることで計画を調整します。 リリース判断可能 スプリントが終わった後には リリース判断可能なプロダクト ができていることが求められます。 リリース判断可能というものがどのような状態を指すものであるかを示すために 完了の定義 を明確にしておきます。 スプリントレビュー スプリントの最後にプロダクトオーナーがスプリントの成果物を確認する機会です。 ここで 実際に動くもの をプロダクトオーナーが確認し、プロダクト バックログ であげていた項目通りのものであれば作業完了となります。 想定通りのものでなかった場合には、次回のスプリントに含むなどの形でプロダクト バックログ に戻します。 スプリントレトロスペクティブ(振り返り) スプリントレビューが終わると、今回のスプリントの振り返りを行います。うまくいったことやよくなかった点を洗い出して今後のスプリントに生かしていきます。 スプリントレトロスペクティブまで完了して1スプリントとなり、プロダクトの完成まで繰り返していくことになります。 終わりに ここまで淡々と スクラム について書いてきましたが、最後に所感を述べて終わりたいと思います。 開発チームの役割で「全員揃えばプロダクトを作れる」というものがありましたが、実際 全員が揃う ことは保証できないですし、 あるキーパーソンがいないと作業が進まないような状況は「属人化」の典型ですし、望ましいものではないです。 そのような状況を改善していくために 個人が複数のことができるようになる 必要があると言えます。 その道のプロフェッショナルであることももちろん重要なことですが、 スクラム では幅広い知識を持った上で参加する必要がありそうです。 また、今学習した部分では スクラム の中には「運用・保守」といった観点は除かれているように感じました。   短期間でリリースをする可能性のある アジャイル 開発において「運用・保守」に与える影響は小さいものではないと考えます。 このような点を解決する考え方として DevOps が生まれてきているわけなので、DevOpsの視点も考慮して開発を進めていく必要がありそうです。 ただし、まだ私は スクラム を体験していませんので間違ったことも多々記載しているかと思います。 実際の スクラム はこれからやっていくことになりますので、次回は実体験から得られたものをご紹介したいと思います。 参考 SCRUM BOOT CAMP THE BOOK スクラムの概要を1分で理解できるイラスト【2018版】 | Ryuzee.com
アバター
はじめに こんにちは。最近 iPhoneアプリ 開発のため Mac に手を出し始めた @rs_tukki です。 前回の記事でも書きましたが、エンジニアは学び続けることが大切です。 ラク スでもTechブログを通したアウトプットを推奨しており、 年齢、拠点に関係なく、 ラク スに所属する全てのエンジニアの方に記事を書いてもらっています。 tech-blog.rakus.co.jp そして、アウトプットを推奨するキャンペーンの一環として先日、ブログの年間表彰式を実施しました! 表彰式の様子 2018年4月1日から2019年3月31日までに記事を投稿された全ての方を対象に、 多くの記事を投稿した方 投稿した記事のアクセス総数が多い方 記事の投稿から一週間のうちに多くのアクセスを獲得した方 その他、ブログの活動に貢献された方 を表彰します。 受賞者には表彰盾のほか、 Kindle など豪華副賞も送られました。 授賞した記事やカテゴリはこちら。 終わらないスクラム カテゴリーの記事一覧 - RAKUS Developers Blog | ラクス エンジニアブログ 5分で理解する!Google Apps Script超入門 - RAKUS Developers Blog | ラクス エンジニアブログ マイクロサービスアーキテクチャにおけるサービス分割の難しさ - RAKUS Developers Blog | ラクス エンジニアブログ 【図多め】APIを使ってGoogleサービスを操る - RAKUS Developers Blog | ラクス エンジニアブログ Android Studioで天気情報を表示するアプリを作ってみた - RAKUS Developers Blog | ラクス エンジニアブログ ラク スでは今後もエンジニア全体で学びを発信していきますので、今後ともよろしくお願いいたします! おまけ 表彰式に参加された方には、このような参加賞もお配りいたしました(笑)
アバター
中小企業の業務効率化に貢献する複数の クラウド サービスを提供する「株式会社 ラク ス」です。東京での3回目の開催となる Meetup イベント RAKUS Meetup #3 を 5/21(火) ラク ス本社@新宿にて開催します。 今回のテーマ 「 Amazon S3 互換ストレージエンジンの導入事例紹介」です。 Amazon S3 はほぼ無制限にスケールするストレージサービスとして広く使われていると思いますが、 セキュリティ上の都合 クライアントとの契約内容 などの理由で クラウド サービスである Amazon S3 が利用できないケースも多々あります。 そんな場合に自前でオブジェクトストレージを構築するという選択があるかと思います。 自前でオブジェクトストレージを構築する際には MinIO 社の minio だとか、 クラウディアン社 の Cloudian Hyperstore などのプロダクトがありますが、今回弊社サービスの 楽楽精算 にて採用されたクラウディアン社の Cloudian Hyperstore の導入事例についてアプリケーションサイド、インフラサイドのそれぞれから紹介させていただこうと思います。 こんな人におすすめ S3などのオブジェクトストレージを導入したいが各種事情からオンプレで構築する必要があるサービスのエンジニア バックエンドエンジニア インフラエンジニア 主にBtoBサービスを提供していて、各種制約のなかサービスをスケールするため日々奮闘しているエンジニア、プロダクトマネージャー、ディレクター BtoBサービス開発者同士の横のつながりを作りたい方 前回の様子 前回開催時の様子は RAKUS Meetup Tokyo #2 フロントエンドNight : イベントレポート をご参照くだい。 開催概要と申し込み 日時: 2019/5/21(火) 19:00-21:00 開場は30分前の18:30からとなります 会場: ラクス 東京本社 セミ ナールーム 〒151-0051 東京都渋谷区 千駄ヶ谷 5-27-11 アグリスクエア新宿2F 参加費: 無料 ハッシュタグ : #RAKUSMeetup 主催: ラクス 申込みは Connpass のイベントページ からお願いします。
アバター
はじめに id:FM_Harmony です、Rakus Developers Blogでは久々の投稿になります。 前回の投稿は 東京開発ビアバッシュに参加しました~2019年2月編~ でした。 tech-blog.rakus.co.jp さて、最近Node.jsの学習を個人的に行っているのですが、学習を進めていく内にJenkinsを用いたCI環境が思いのほか簡単に構築できることが分かりました。 そこで今回は、Jenkinsを用いたNode.jsアプリのCI環境の構築手順について記事を書きました。Node.jsでアプリを開発されている方の参考になれば幸いです。 なお、Jenkinsのバージョンは ver. 2.173 を利用しているため、それ以外のバージョンを利用している場合、設定内容等に差異があるかもしれません。 目次 はじめに 目次 Jenkinsの設定 NodeJS Pluginの導入 NodeJSの設定項目 Install from nodejs.orgの設定項目 ジョブでインストール状況を確認する 自動テストを試してみる サンプルプロジェクトの作成 単体テストの作成 レポートファイルを出力する JenkinsでCI用ジョブを作成する おわりに 参考 Jenkinsの設定 NodeJS Pluginの導入 「NodeJS Plugin」を利用することでJenkinsがNode.jsを実行するための設定を簡潔に行うことができます。 Top画面 > Jenkinsの管理 > プラグインの管理 から「NodeJS Plugin」をJenkinsにインストールします。 NodeJS Pluginのインストール 導入後、再起動したらPluginが反映されるので、次にJenkinsで利用するNode.jsの設定を行います。 Top画面 > Jenkinsの管理 > Global Tool Configuration に、「NodeJS」という項目が増えているはずなので、そこから設定を行います。 何も設定していなければ、「NodeJS追加」ボタンを押下することで、Node.jsの設定を追加することができます。また、複数バージョンのNode.jsを利用するように設定することもできます NodeJSの設定項目 名前 Jenkinsのジョブで利用する際に指定する 自動インストール チェックを入れるとJenkinsが自動でNode.jsをインストールする。初期の インストーラ として「Install from nodejs.org」が設定されており、基本的には インストーラ を変更する必要はない インストール ディレクト リ 自動インストールにチェックを入れない場合は入力、今回は利用しない Install from nodejs.orgの設定項目 Version 利用するNode.jsのバージョン Force 32bit architecture 今回は利用しないが、32bitOSの場合は必要かもしれない Global npm packages to install npmで利用するグローバルパッケージの指定。基本的にパッケージ名を指定すればよいが、 packageName@version と記載することで指定のバージョンをインストールさせることができる? Global npm packages refresh hours 初期値で問題なかったので、しっかりとは調べていない... 今回は記事作成時点で最新かつ安定のNode.jsを利用する、mochaで 単体テスト を行いJenkinsでレポートを集計するようにするため、以下のように設定しました。 NodeJS Pluginの設定 ジョブでインストール状況を確認する 以下の設定内容でフリースタイル・プロジェクトのビルドジョブを作成してNode.jsのバージョンやnpmパッケージのインストール状況を確認してみます。 ビルド環境 Provide Node & npm bin/ folder to PATHにチェックを入れ、以下の通り設定 NodeJS Installation NodeJSの設定項目で「名前」に入力したもの npmrc file 特別に設定していなければ、 -use system default- しか表示されていないはず ビルド 以下の シェルスクリプト を実行する node --version npm ls --depth=0 -g ビルド実行が成功し、ビルドのコンソール出力に以下のような内容が表示されていれば設定は期待通りになっているはずです。(今回はJenkinsを tomcat に載せています) Started by user xxx Running as SYSTEM Building in workspace /home/tomcat/.jenkins/workspace/NodeJSConfigurationCheck [WS-CLEANUP] Deleting project workspace... [WS-CLEANUP] Deferred wipeout is used... [WS-CLEANUP] Done [NodeJSConfigurationCheck] $ /bin/sh -xe /opt/tomcat/temp/jenkins8667759308635013491.sh + node --version v10.15.3 + npm ls --depth=0 -g /home/tomcat/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_v10.15.3/lib ├── mocha@6.1.3 ├── mocha-junit-reporter@1.21.0 └── npm@6.4.1 Finished: SUCCESS 自動テストを試してみる サンプルプロジェクトの作成 今回は以下のような構成のプロジェクトを作成してみます。 サンプルプロジェクト ├─node_modules ├─src │ ├─index.js │ └─calc.js ├─test │ └─calcTest.js ├─package.json └─package-lock.json 各ファイルの説明は以下の通りです。 src/index.js アプリケーションのエントリポイント src/calc.js 計算を行うモジュール test/calcTest.js src/calc.js の 単体テスト それ以外はnpmで自動的に作成されるファイルです。 まずは、 mocha + power-assert で 単体テスト を行いたいので、プロジェクトのルート ディレクト リで以下を実行します。 npm init npm install -g mocha mocha-junit-reporter npm install --save-dev power-assert intelli-espower-loader 次に、 index.js 、 calc.js を作成します。今回は、index.jsをnodeで起動して、引数として渡した2つの数値を足したものがコンソールに表示されるようにします。 // index.js 'use strict' ; var calc = require( './calc' ); if (require.main === module) { main( { argv: process.argv } ); } function main(options) { var argv = options.argv; var x = parseInt(argv [ 2 ] ); var y = parseInt(argv [ 3 ] ); var result = calc.add(x, y); console.log(x + '+' + y + '=' + result); } // calc.js 'use strict' exports.add = function (x, y) { return x + y; } ; ルート ディレクト リでindex.jsを実行してみると、以下のようにコンソール表示が行われるはずです。 $ node src/index.js 1 2 1+2=3 単体テスト の作成 次に、 calc.js の 単体テスト を作成します。今回は、テストとして 1+1=2を満たす ことをテスト成功の条件にしてみます。 //calcTest.js 'use strict' var assert = require( 'power-assert' ); var calc = require( '../src/calc' ); describe( 'addファンクションの単体テスト' , function () { it( 'add(1, 1) = 2' , function () { var result = calc.add(1, 1); assert.strictEqual(result, 2); } ); } ); ローカルで 単体テスト を実行してみます。ルート ディレクト リで mocha を実行すれば良いです。 $ mocha addファンクションの単体テスト √ add(1, 1) = 2 1 passing (15ms) レポートファイルを出力する package. json を編集してレポートファイルを出力するようにします、以下の設定を追記して npm test を実行すると、デフォルトではルート ディレクト リの test-results.xml にテスト結果が出力されるはずです。 " scripts ": { " test ": " mocha test --reporter mocha-junit-reporter " } , // test-results.xml <?xml version="1.0" encoding="UTF-8"?> <testsuites name="Mocha Tests" time="0.001" tests="1" failures="0"> <testsuite name="Root Suite" timestamp="2019-04-16T04:39:33" tests="0" failures="0" time="0"> </testsuite> <testsuite name="addファンクションの単体テスト" timestamp="2019-04-16T04:39:33" tests="1" file="C:\Users\kazuki.hirayama\Desktop\NodeJSCISample\test\calcTest.js" failures="0" time="0.001"> <testcase name="addファンクションの単体テスト add(1, 1) = 2" time="0.001" classname="add(1, 1) = 2"> </testcase> </testsuite> </testsuites> この時点で、CI連携用に Github の リポジトリ へpushしておきます。 JenkinsでCI用ジョブを作成する 最後にCI用のジョブを作成しましょう。フリースタイルビルドジョブを以下のように設定します。 ※ Github との連携に関するところは割愛します ビルド環境 「ジョブでインストール状況を確認する」の際に設定したもの ビルド シェルの実行 npm install npm test ビルド後の処理 JUnit テスト結果の集計 テスト結果 XML デフォルトであれば、 test-results.xml を入力 それ以外の項目 とくに変更しない この後、 Github の リポジトリ へpushを行うとビルドが始まるはずです。ビルドが成功して、成功後のコンソール出力が以下のようになっていれば期待通りです。 Started by GitHub push by xxx Running as SYSTEM Building in workspace /home/tomcat/.jenkins/workspace/NodeJSSampleCI No credentials specified Cloning the remote Git repository Cloning repository xxx > git init /home/tomcat/.jenkins/workspace/NodeJSSampleCI # timeout=10 Fetching upstream changes from xxx > git --version # timeout=10 > git fetch --tags --progress xxx +refs/heads/*:refs/remotes/origin/* > git config remote.origin.url xxx # timeout=10 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url xxx # timeout=10 Fetching upstream changes from xxx > git fetch --tags --progress xxx +refs/heads/*:refs/remotes/origin/* > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10 Checking out Revision 9600a7cf391f3aea917dc06db88b84851d7de87b (refs/remotes/origin/master) > git config core.sparsecheckout # timeout=10 > git checkout -f 9600a7cf391f3aea917dc06db88b84851d7de87b Commit message: "test commit" First time build. Skipping changelog. [NodeJSSampleCI] $ /bin/sh -xe /opt/tomcat/temp/jenkins7429977434779181980.sh + npm install npm WARN nodejscisample@1.0.0 No description added 79 packages from 155 contributors and audited 280 packages in 2.283s found 0 vulnerabilities + npm test > nodejscisample@1.0.0 test /home/tomcat/.jenkins/workspace/NodeJSSampleCI > mocha test --reporter mocha-junit-reporter Recording test results Finished: SUCCESS また、ビルドの「テスト結果」から下記画像のようなテスト結果を取得できるはずです。 テスト結果 おわりに いかがでしたでしょうか、「NodeJS Plugin」を利用することでNode.jsのアプリケーションをJenkinsでCIする環境が容易に構築できることがお分かりいただけたかと思います。基本的に プラグイン の設定のみで完結するため、 個人的にはサーバで直接作業をする必要がないのが嬉しいと感じています。 まだまだ自身もCIやJenkinsについて不勉強な面がありますので、今後も学習していこうと思います。 参考 爆速でJenkinsをマスターしよう(NodeJS編) ~ JenkinsセットアップからNodeJS自動テスト、Job DSLまで ~ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター