株式会社medibaのブログ - TECH PLAY

TECH PLAY

株式会社mediba

株式会社mediba の技術ブログ

210

こんにちは。制作部の苅部です。 今回WebStormというIDEついてご紹介したいと思います。 私自身これまでエディタとしてSublime Textを使っていてIDEを触ったことがなかったのですが、実務の中でWebStormを試す機会があったので、備忘録も兼ねて便利な機能をまとめてみたいと思います。 私のように選ばずに一つのエディタを使い続けてきた方に向けて、WebStormの実際に使ってみないと分からない部分を簡単にご紹介できたらと思います。 IDEと聞くと敷居が高く感じるかもしれませんが、使いこなすと手放せなくなると思います。 エディタやIDE選択の一助となれば幸いです。 WebStormとは チェコ共和国のプラハに本社を置くJetBrainsというソフトウェア会社が開発しているIDE(統合開発環境)です。 同社が開発しているIntelliJ PlatformをベースにWeb開発に機能を絞ったものがWebStormとなります。 “The smartest JavaScript IDE"のキャッチコピーの通りJavaScriptでの開発を強力に支援してくれますが、フロントエンドのサポートは幅広くモダンな開発環境に限らずとも生産性を高める事が出来ると思います。 今回は2016年4月時点の最新バージョン、WebStorm 2016.1(OS X)をベースに以下の項目でまとめてみました。 さまざまな機能の統合 豊富なコード支援 デバッグ支援とコード品質の安定化 プラグインでの拡張 ※WebStormとしての紹介となりますが、おそらくPhpStormでも同等の機能があるのではないかと思います。 1) さまざまな機能の統合 WebStormでは開発を支援する多くの機能を内包しているので、同時に利用するアプリケーションやウインドウの数を減らし一つの画面に集中して作業をする事ができます。 例えばテストツール・タスクランナー・仮装環境などはそれぞれ別のCLIにせずIDEの中にインターフェイスを統合できます。 テストランナー テストランナーのKarmaをサポートしており各テストコードをRunタスクとして登録することができ、UI上でテスト実行やテスト結果の確認をすることができます。 タスクランナー GruntやGulp,npm-scriptsと連携可能です。 例えばファイルの変更検知などで常時利用するようなタスクは、プロジェクトを開いた際に自動実行する事によって、CLIから開始する必要もなくなります。 それぞれのタスクはGUIで一覧表示が可能で、任意のタスクの実行やコード行へのジャンプも可能です。 タスクの数が増えてしまい全体を把握しづらくなった場合に便利です。 Vagrant VagrantのログもRunウィンドウの中で表示可能です。そしてアクションの実行もWebStorm上から可能です。 ビルトインターミナル IDEから離れることなくCLIの操作が可能で、タブでの複数表示や[Cmd+F]での検索も利用できます。 ビルトインサーバやちょっとしたNode操作/ファイル操作など、CLIを使う機会は多いため開発環境にターミナルが組み込まれているのは本当に便利です。 RESTクライアント RESTクライアントがビルトインされているため、IDE内で気軽にWEBサーバへのリクエストのテストができます。 そのためDevHTTPClientなどの別クライアントも不要になります。 VCS GIT(とGitHub)やSubversionとの連携が可能です。 VCSウインドウからコミットやブランチの切り替えなどの通常操作もできますし、ファイルツリーでは未コミットファイルのアイコン色が変化したり、メインウインドウの右下でも現在のブランチ名表示やブランチ切り替えができます。 WebStormのUIは全体的にVCSとの親和性が高いように思います。 またGithubとコネクトする事によりPullRequestやIssue操作もできます。 大抵のGit操作はWebStorm内で完結させる事ができるのではないでしょうか。 TODO エディタでの開発ではあまり馴染みがないですが、コメントアウトの文字列でTODO管理ができます。 後回しにする実装などを"TODO"から始まるコメントアウトで残しておくことで、TODOウインドウ上に一覧表示させる事が可能です。 開発が長期にわたるプロジェクトで重宝すると思います。 マークダウンプレビュー マークダウンファイルのプレビューが可能です。 ATOMのようなライブプレビューではないものの、簡易的なレイアウト確認で役に立ちます。 FTPクライアント FTPクライアントも組み込まれていますので、CyberduckやFileZillaのような個別のクライアントも不要になります。 使い勝手についてもアップロード程度の作業であれば全く問題ないと思います。 ローカルヒストリー ローカルでの作業履歴が逐一保存されているので、思わぬアクシデントでのコード消失を防ぐことができます。 個々のログで差分を比較したりある時点の内容へリバートできるので、安心して作業をする事ができます。 横断検索 [Shift]キーを2回押下する事で、ファイルやIDE機能の横断検索が可能です。 キーボードショートカットやIDEの機能名、ファイル名を忘れてしまった場合でも、曖昧な検索ワードで目的の機能やファイルを見つけ出す事ができます。 構造表示 HTML/CSS/JavaScriptファイルの内容を構造的に表示できます。 コードの行数が長かったりネストが深い場合でも見通しが良くなるため、設計の全体を俯瞰できるようになります。 プレゼンテーションモード IDE自体のインターフェイスやコードの文字を大幅に拡大するプレゼンモードがあります。 画面を使って人に説明するときや、プロジェクタなどに映し出すときに便利です。 プレゼンテーションモードでの文字サイズは設定画面から変更する事が可能です。 以上のように、多くの機能がIDEに統合されているので、コーディングに必要なUIをほぼ1画面で収めて快適に作業を進める事ができます。 参考レイアウト: ある程度解像度の余裕があればWebStormとブラウザを並べる事でさらに作業が捗ると思います。(OS XのSplitViewを使うとうまく収まります) 2) 豊富なコード支援 高機能なエディタによって、入力支援や入力中でのコード解析が可能です。 JavaScriptではES6/Node.js/AngularJS/React/Angular2/AltJSをサポートしていて、それぞれコード補完やハイライティング、コンパイル機能などを搭載しています。 プロジェクトごとに設定画面からJavaScriptのバージョンを選ぶ事ができるのでES6への切り替えも簡単ですし、宣言元へのジャンプ機能も備えています。 HTMLはEmmetやHTMLタグの入力補助、CSSも各種メタ言語をサポートしています。 コードヒント 推測精度の高いコードヒントを利用可能で、例えば以下のような形で頭文字で候補を絞り込むことが可能です。 gebi > getElementById() qsa > querySelectorAll() euc > encodeURIComponent() duc > decodeURIComponent() Postfixコード補完 任意の値の後に.(ドット)でキーワードを繋げて[Tab]を押下するとコードブロックとして整形できます。 console.log()のようなものは利用頻度が高くタイプ数も減らせるので便利だと思います。 ※Postfixの候補を自分自身で作成する事も可能です。 hoge.log > console.log(hoge) hoge.return > return hoge hoge.null > if (hoge == null) {} hoge.notnull > if (hoge != null) {} hoge.if > if(hoge) Emmetサポート 標準でHTML/CSS/JSXファイル上でのEmmet記法に対応しているので、タイプ数を減らしコーディングスピードを上げる事ができます。 私はまだEmmetを使いこなせていないのですが、シンプルなhtml入力はEmmetに頼るようになりました。 Imgタグ入力補助 Imgタグにsrc属性が指定されている場合は、画像のサイズを候補で表示をしたり、画像のプレビューを表示をすることができます。 マークアップの最中にFinderで画像の情報を確認するのは煩わしいので、これはなかなか便利です。 ※src属性にフォーカスしながら[Shift]でサムネイル表示、[Cmd]で画像を別ウインドウで開く事ができます。 LiveEdit JetBrains社製のChrome拡張を追加してLiveEdit機能を有効にすることで、HTML/CSSの変更をリアルタイムにChromeでプレビューすることができます。 そのためファイル変更の度にブラウザをリロードする必要がなくなります。 JetBrains IDE Support - Chrome Web Store またLiveEditではJavaScriptのConsoleもChrome側ではなくIDE上でも確認できます。 CSS SASS/LESS/Stylusなどのメタ言語に対応しているためシンタックスハイライトや色ピックアップ、変数の候補表示が可能です。 JavaScriptと同様にコード分析によってQuick-Fixが利用可能で、例えばショートハンドプロパティが利用可能な場合では、その場で[Alt]+[Enter]でQuick-Fixができます。 リファクタ可能な箇所はスマートに修正ができるようになります。 またCSS Stylesタブでは、ブラウザのインスペクタを使っているような感覚で選択中のHTMLのCSSStyleを確認する事が可能です。 JavaScript 宣言元ジャンプ [Cmd]+[b]で宣言元へのジャンプや、呼び出し元へのジャンプも可能です。 開発では特にこの機能を使う事が多いのではないでしょうか。 JSDoc JSDocをサポートしていて、関数の内容を解析した上でコメント生成の補助をしてくれます。 改行位置も綺麗に整いますしドキュメント整備が快適に進められます。 以上ご紹介した機能以外にも [Option]+[Enter]での正規表現のバリデータを利用できたり、 Auto IndentやReformatCodeによるコード整理 Refactorによる安全なファイル・クラス置換 LiveTemplateでのスニペット機能 などなど、多くの機能を備えています。 3) デバッグ支援とコード品質の安定化 クライアントサイド/サーバサイドのJavaScriptのデバッグができ、テストランナーやLinterと連携ができます。 またIDEでのコードスタイル定義や定義ファイル自体のバージョン管理により、一貫したコードスタイルを保てると思います。 テストランナーとの連携 Karmaに採用されているカバレッジエンジンのIstanbulに対応しており、npmでkarma-coverageをインストールすればカバレッジ状況を表示することも可能です。 UI上にカバレッジを表示する事で、普段からテストを意識する事に繋がると思います。 コード行におけるcovered/uncoveredの表示もハイライトで確認する事ができます。 Linter JSHint/JSLint/ESLint/JSCSなどのLinterやスタイルチェッカーを搭載していて、コードは常時解析されているためエラーがあればタイプ直後に反応します。 Grunt/GulpなどのタスクランナーでLinterを走らせるよりもレスポンスが早くなると思います。 また、コードに問題がある場合はQuick-Fixオプションで即座に修正可能です。 JSHint/JSLintそれぞれの設定では、チェック対象を細かく指定できます。 この他にもデバッグをサポートする、 Spy-jsによるコード実行のトレース Node.jsアプリケーションのCPU profilesやHeap snapshotsの確認 JSTestDriver/Cucumber.jsのサポート ES6やTypeScript、CoffeeScriptでもソースマップをサポート といった様々な機能が含まれているようです。 4) プラグインでの拡張 IDE Plugin Repositoryに数多くのプラグインが用意されていて、好みに合わせてIDEをカスタマイズする事が可能です。 ここでは私が利用しているプラグインを2つご紹介します。 Material Theme UI UIの見た目をすっきりとしたマテリアルデザイン風に変更できます。 ※テーマはプラグイン経由に限らず非公式のWebサイトから探す事もできます。 Color Themes gfm マークダウンのプレビューをGFM(GitHub Flavored Markdown)で表示する事ができます。 WebStorm標準のマークダウンプレビューは簡素なため、見た目を良い具合にGithub風に整えてくれるこのプラグインは重宝しています。 gfm-plugin ライセンス体系 JetBrains社は2015年にライセンス体系をサブスクリプションタイプに変更していて、2016年4月時点でのライセンスは以下のような設定になっています。 個人利用 商用利用 ・年間契約   初年度 $59.00   2年目 $47.00   3年目 $35.00 ・月間契約   毎月 $5.90 ・年間契約   初年度 $129.00   2年目 $103.00   3年目 $77.00 ・月間契約   毎月 $12.90 いずれもサブスクリプションのため継続した支払い体系になりますが、必要な期間だけ月間契約で継続してみる、といった選択肢があるのもメリットだと思います。 また、JetBrains社は機能追加やバグフィックスへの対応のために 製品のリリース頻度を高めて いるようです。 2016.1のリリースで既にCSS custom variableのサポートがされていますし、2016.1のリリース以降も短いスパンでバグフィックスや機能追加のアップデータが繰り返し配布されています。 Web開発は技術のアップデートサイクルがとても短いので、常に最新の状態で利用できることのメリットは大きいと思います。 まとめ WebStormは"全部入り"のIDEとなっており私もすべての機能を把握できていませんが、使いこなす事が出来れば多機能ゆえの楽しさもあると思います。 実務の中でしばらく使ってみて、 充実したコード支援機能でのコード品質の安定化 キーボードショートカット中心の操作による作業スピード向上 インターフェイスの統一による作業効率の向上 を実感できて、JavaScriptメインの開発環境でなくても十分活用できると感じました。 またチーム内でのコーディングスタイルを統一しやすくなりますし、UIの分かりやすさはデザイナーが開発に携わる場合にもメリットがある思います。 エディタに比べると高機能ですのでそれなりのマシンパワーが必要とされますし、シンプルか多機能かは好みでもありますが、統一されたGUIならではの扱いやすさは確実にあると思います。 今回は全体の機能を通しでまとめましたが、 もう少し使い慣れてきたら個々の機能にフォーカスしてまたご紹介したいと思います。  参考URL WebStorm WebStorm 2016.1 Help YouTube - JetBrains Playlist YouTube - WebStorm - Things You Probably Didn’t Know Qiita - WebStorm
こんにちは、品質管理グループの 山本久仁朗です。 みなさんの組織では、テスト計画を作成していますか? テスト計画について、さまざまな効果があることは、みなさんご承知のことと思いますが、 今回はマスターテスト計画の活用について、お話しいたします。 マスターテスト計画の役割 IEEE 829 や ISO/IEC/IEEE 29119 などに含まれる、ソフトウェア・システムのテスト計画書の多くは、 PMBOK のプロジェクト計画と親和性が高く、テストの要件・目的・対象・期間・範囲・粒度・工数・開始終了基準・成果物等が含まれ、合意形成や手戻りに抑止等の効果があります。 ただし大きなプロジェクトにおいて、各機能・フェーズに対応した各レベルテスト計画だけでは整合性が取れず、サービスを全体的に見ると、テストの抜け・漏れ・重複が発生するリスクが残ってしてしまいます。 マスターテスト計画は、このような抜け・漏れ・重複を削減し、よりスムーズにテストを進めるために、プロジェクト・サービス全体を俯瞰して考える役割を担っています。 マスターテスト計画導入の効果 サービス全体でMECE(抜け・漏れ・重複なし)なテストを実施 各レベルテストのテスト目的・観点・スコープを確認し、サービス全体のテスト観点として抜け・漏れ・重複は無いかを精査することで、より効率的なテストが可能になります。 直近の事例として、マスターテスト計画をベースに各レベルテストのテスト観点の抜け漏れが判明したので、 下流のレベルテスト計画を見直しすることにより、初期計画時の3倍の不具合を検出することができました。 レベルテストをブラッシュアップして、早期に不具合を検出 各レベルテストの目的から、テスト観点毎にテスト対象・実施時期を再調整して、 早期にテストを段階的に実施することで、品質状況も段階的に可視化・共有可能になります。 実際に、設計側と相談して、主要な機能をプレリリースしてもらうことで、1~2週間ほど先行して一部機能のテストが実施できるようになりました。 上記のように、マスターテスト計画には大規模・複雑なシステム・サービスをテストする際に、レベルテスト計画を補完する効果がありますが、決して良い話ばかりではありません。そこには、陥りがちなアンチパターンがたくさんありました。 代表的な例を列挙いたしますので、お気を付けください。 マスターテスト計画導入時のアンチパターン マスターテスト計画を導入してみた方は、ご存知のことと思いますが、さまざまな課題が発生します。例えば、そもそもどうやったらいいのか分からない・工数がかかる・効果が分からない等いろいろな理由から、なかなか安定運用できていないのが現状だと思います。 そこで、いままでの経験をベースに、いくつかのアンチパターンを列挙します。 レベルテスト・フェーズが相互補完していない テスト観点が漏れて、後工程・市場で障害が発生する 同じテストケースを使いまわしているが、最適化されない 規格に規定されているすべての項目を列挙して、膨大なテスト計画になる 計画書の項目を埋めるために、必要性が低い情報を収集して工数がかかる メンテナンスに工数がかかる → 工数がかかるので見直しをしない → 現実と乖離する 各レベルテストを分割せずに変化に対応できない 829-1998等をベースに、1つの大きなテスト計画を作成し、変更し辛いドキュメントになる 目的・スコープ等から分割した方が柔軟性が高まるが、結合・総合・システム等のフェーズに縛られ分割できない マスターテスト計画導入時のおすすめパターン 私が、マスターテスト計画でもっとも重要視しているのは、integrity(完全性)です。 サービス全体で実現すべきテスト観点が過不足ないか確認しています。 しかし、各レベルテストのテスト設計・実装内容まで確認すると、対費用効果が低くなり、いくら工数があっても足らなくなります。 そこで、下記のようなポイントを軸に、ライトに何度も見直しができるような運用を心がけています。 テスト観点ベースでのヒアリング実施(目的・スコープ・アプローチ程度) 各レベルテストの状況から、不足しているテスト観点・タスクを検討・調整 計画時のテスト観点をもとにテスト設計・実装を実施 まとめ 上記の事例は、非常に効果的に実施できた例になりますが、マスターテスト計画の活用方法を見直すことで、不具合を早期に検出して、検出効率を向上させることができました。 みなさんの現場において、テスト計画の見直し、より早期の不具合検出、効率的なテストの推進・実施等の一助になれば幸いです。
こんにちは。年度が替わりましてスマートパス開発部からインフラ部へ異動した子安です。最近すっかり暖かくなって、日本人で良かったなと思っています。 さて、近年いろいろな動画学習サービスが提供されていて楽しいですね。動画学習といえば、ブラウザで動画を見ながらエディタでコードを書いてコンソールで実行、をコツコツやるわけですが、3つのことを同時に進めていくのは大変面倒です。面倒なので書いたコードを保存したら自動的に実行されるようにしたいと考え始めました。そこで、タスクランナーとしてよく聞くGulpとかGruntとかをこの機会に試してみます。 そもそもGulpもGruntも今まで触った経験がないのですが、どっちがナウいんでしょうか。社内で聞いてみました。 え、オワコン・・・!? そうなのか・・・まあでも、実際に自分でも触ってみないとわかりませんよね。 初めに実現したいことをまとめておきます。 今は自分的にGoが流行ってるのでGoの動画を見て勉強するつもり goファイルはプロジェクト配下のsrc/ディレクトリに格納する コードを編集・保存したら、そのファイルに対して自動的に go run を実行する 実行結果はコンソールに表示する。実行する度にコンソールをクリアする 環境はMac OS X(10.11.4)で、Go・Node.jsをインストール済み Gulp まずはロゴがかっこいいGulpから。 npmを初期化してGulpをインストールします。Gulpの設定ファイルはせっかくなのでCoffeeScriptで書きましょう。CoffeeScriptもインストールしておきます。 npm init npm install --save-dev gulp coffee-script ファイルの変更監視は gulp.watch で行います。設定ファイル:gulpfile.coffeeはこんな感じになります。 # gulpfile.coffee gulp = require 'gulp' {spawn} = require 'child_process' gulp.task 'watch', () -> gulp.watch 'src/**/*.go', (event) -> if event.type in ['added', 'changed'] console.log '\x1b[2J' spawn 'go', ['run', event.path], {stdio: 'inherit'} gulp.task 'default', ['watch'] これを下記のコマンドで実行します。 $(npm bin)/gulp Grunt 次はGruntでやってみましょう。npmを初期化してGruntをインストールします。こちらも設定ファイルはCoffeeScriptで書くことにしますが、依存関係に含まれるためCoffeeScriptを個別にインストールする必要はありません。代わりにファイルの変更監視のためのプラグインが必要になります。 npm init npm install --save-dev grunt grunt-contrib-watch watchプラグインを設定し、イベントを捕まえて go run コマンドを実行するようにします。設定ファイル:Gruntfile.coffeeはこんな感じになります。 # Gruntfile.coffee {spawn} = require 'child_process' module.exports = (grunt) -> grunt.initConfig watch: files: ['src/**/*.go'] options: event: ['added', 'changed'] grunt.event.on 'watch', (action, filepath, target) -> console.log '\x1b[2J' spawn 'go', ['run', filepath], {stdio: 'inherit'} grunt.loadNpmTasks 'grunt-contrib-watch' grunt.registerTask 'default', ['watch'] これを下記のコマンドで実行します。 $(npm bin)/grunt npm-scripts 最近はGulpやGruntを使わずにnpm-scriptsを使うんだという話なので、その方法も試してみたいと思います。例によってnpmを初期化して、CoffeeScriptとファイルの変更を監視してくれるchokidarというパッケージをインストールします。 npm init npm install --save-dev coffee-script chokidar package.json(抜粋)はこんな感じで "scripts": { "watch": "coffee watch.coffee" }, 呼び出すwatch.coffeeはこうなります。 # watch.coffee chokidar = require 'chokidar' {spawn} = require 'child_process' chokidar.watch './src/**/*.go', ignoreInitial: true .on 'all', (event, path) -> if event in ['add', 'change'] console.log '\x1b[2J' spawn 'go', ['run', path], {stdio: 'inherit'} これを下記のコマンドで実行します。 npm run watch まとめ Gulp・Grunt・npm-scriptsのいずれの方法でも、実現したかったことを実現できました。 出来上がった設定ファイルを見てみると、GruntはGulpに比べて決まり文句的な記述が多く、設定を宣言的に行うようになっているため柔軟性に欠けるという印象です。Gulpとnpm-scriptsに関しては、記述内容自体にほとんど差がないですね。 それよりもそれぞれのプラグインを探すことや、Gulp・Gruntの書き方を調べることに時間がかかりました。使うために調べることが多くなってしまうのはツールとして本末転倒なので、熟れるまで使い込めるかどうかを判断する必要がありそうです。 使ったもの Node.js: v5.10.0 npm: v3.8.3 Gulp: v3.9.1 Grunt: v1.0.0 CoffeeScript: 1.10.0 コードは GitHub に置いています。 おまけ というようなわけで、今回はnpmでどうやるかということを調べてきたのですが、ここまで来るともうnpmである必要もない気がしてきました。 探してみたところ、Homebrewにfswatchというコマンドがありました。 brew install fswatch このコマンドは監視対象のファイルにイベントがあると、標準出力にファイルパス等を書き出してくれます。つまり、 fswatch -0 --include='\.go$' --exclude='.*' --event=Created --event=Updated ./src | \ while read -d '' file; do echo $'\e[2J' go run "${file}" done おやおや、一番簡単でした!これが正解だったみたいですね。
こんにちは! mediba 制作部でデザイナーをしている森本です。 お仕事でイラストを描く場面が多々あるのですが、今までは手描きのラフを Illustratorで読み込み、手でトレースしたりしていました。 細かいことは好きなのでそんなに苦にはならないのですが、やはり時間がかかる… ということで、最近は気が付くと色々なアプリがリリースされているAdobe CCの中から、 Adobe Capture CC というアプリを使ってみましたのでご紹介したいと思います。 まず、Adobe Capture CCとは? iPhoneなどで撮影した画像を取り込み、ベクトル画像に変換し、 シェイプとしてIllustratorやPhotoshopで使用できるというとても便利なアプリです! 手描きしたイラストを撮影し、写真からパスを作成することが出来るので、 今までトレースしていた時間も短縮できますね。 Adobe Capture CCアプリを開きます 使い方はとっても簡単! まずは iTunes App Store や Google Play で、 Adobe Capture CC をダウンロードします。 無償または有償のCreative Cloudメンバーシップが必要です。 使用前にAdobe IDでサインインしてください。 キャプチャをベクターシェイプに変換する 1.イラストを描く 今回は私が大好きなシロクマを描いてみました! 2.Adobe Capture CC へ取り込む SHAPESメニューを選択し、『 + 』アイコンをタップします。 3.イラストを撮影する カメラをイラストに向けると、主なトレースラインが緑色でハイライト表示されるので、スライダーを動かしながら最適な結果になるようコントラストの調整をし、シェイプを保存します。 (右下のアイコンから、カメラロール、Creative Cloud内の画像を選択することもできます。) 4.パスの調整をする 『 パスを削除 』でいらない要素を削除して調整していく。 一度削除しても『 削除を取り消し 』で戻すことができます。 5.プレビューで確認 『 次へ 』をタップするとなめらかな曲線にしてくれます。 6.シェイプを保存する 『 次へ 』をタップし、わかりやすい名前をつけて保存先のライブラリを新規作成もしくは選択。 『 SHAPEを保存 』をタップすると、マイライブラリ内のSHAPES へ保存されます。 続いては、イラストで使うカラーを決めていきたいと思います。 1枚の画像からカラーテーマを作成する 1.カラーテーマ用の画像を撮影する COLORSメニューを選択し、『 + 』アイコンをタップします。 カメラを対象に向けると、アプリが自動的にシーンから5つのカラーを選択。 ポインターをドラッグしてそれぞれのカラースウォッチを調整し、カラーテーマを保存します。 (右下のアイコンから、カメラロール、Creative Cloud内の画像を選択することもできます。) 2.カラーテーマを保存する テーマ名をわかりやすい名前に変更し『 COLOR テーマを保存 』をタップするとマイライブラリ内のCOLORS へ保存されます。 3.Illustratorで読み込む 保存をすると、同期をしているIllustratorのライブラリ内にシェイプとカラーテーマが反映されるので、ライブラリからドラッグでアートボードへ移動し、Illustrator上で編集することができます。 4.Illustrator上でイラストを編集したら完成です! Adobe Capture CCを使ってみて感じたこと ・手描き風などのシンプルなイラストであればそのまま使えるので便利! ・ラフ段階のイラストをデータ化して見せたい時に使える ・線が塗りで取り込まれるので、編集したい場合には少し手がかかる ・そのため手の込んだイラストを描きたい時には結局Illustratorでトレースしたくなりそう… などなど、線で取り込めるようになればこのアプリ、もっと使い方が広がるなぁと感じました。 まだまだ改良中のようですので、今後に期待します! 長い記事を最後まで読んでいただき、ありがとうございました!
こんにちは、メディアシステム開発部の竹谷です。 私のチームではAWS CodeDeployを使っているのですが、デプロイ結果をSlackに流せないかなと思って調べてみました。 CodeDeployは、デプロイのステータスをAWS SNSに流すことができるので、CodeDeploy→SNS→Lambda→Slackといった流れで実現してみました。 SNSの設定 まずは、CodeDeployのステータスを流すSNS topicを新規作成します。 CodeDeployの設定 トリガーの作成から、デプロイステータスをSNSに送る設定を行います。 作成したSNS topicを指定します。 Lambda functionの作成 次にLambda functionの作成ですが、Lambdaを実行するIAM Roleをあらかじめ作っておきます。 最低限AWSLambdaExecuteが必要です。 Lambda functionを作成します。 今回はPythonで作成します。右下のsns-message-pythonを選びます。 作成したSNS topicを選択します。 Roleには作成しておいたRoleを指定します。 コードは以下のような感じです。 (requests ライブラリを使用していますので、実際にはパッケージ化する必要があります) import json import requests def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) message = event['Records'][0]['Sns']['Message'] print("From SNS: " + message) messageDict = json.loads(message) if messageDict['status'] == 'FAILED': slackColor = 'danger' slackValue = messageDict['errorInformation'] else: slackColor = 'good' slackValue = messageDict['status'] url = 'https://hooks.slack.com/services/xxxxx/xxxxx' payload = { 'channel': '#deploy', 'username': 'CodeDeploy', 'icon_emoji': ':shipit:', 'attachments': [ { 'fallback': 'code deploy status : ' + messageDict['deploymentGroupName'] + ' : ' + messageDict['status'], 'color': slackColor, 'title': messageDict['deploymentGroupName'] + ' : ' + messageDict['status'], 'text': slackValue } ] } headers = {'content-type': 'application/json'} r = requests.post(url, data=json.dumps(payload), headers=headers) return message CodeDeployを動かしてみる Lambda functionを作成して、実際にCodeDeployを動かすとSlackに流れることが確認できました。 デプロイ開始と成功した場合。 デプロイ失敗した場合。 まとめ デプロイ結果がSlackに流れると便利ですね。
こんにちは、CTOをしている山田です。 JAWS DAYS2016参加してきました。何と参加者が1100名以上だったようで、すごい盛り上がりでした。 改めてコミュニティの凄さとそれを惹きつけるAWSの魅力を実感しております。また、隅々まで気配りが行き届いた本当に素晴らしいイベントでした。 運営者の皆様お疲れ様でした。 私はユーザートラックの「 ユーザの本音、AWS入れてどうなった? 」というパネルディスカッションにパネラーとして参加してきましたので、そこでお話した内容をまとめます。 このセッションは、これからAWSを導入、もしくは導入間もない方向けに、導入前後の変化や導入後に出た課題、次どういうことをしていくかというディスカッションでした。 まずは自己紹介を交えてお話しした内容です。 導入した目的 ビジネス側から要求を満たすために2つの大きな課題があり、どうしてもインフラがボトルネックになってしまうため、クラウドの採用は必然でした。 開発のアジリティを大きく向上させる必要があった 読めないトラフィックに対応する必要があった 提供されているサービスのカバー領域、情報量、コミュニティの存在、AWSのサポート体制、エンジニアの興味ということでAWSの採用に至りました。 なお、現在もですが、導入当時から クラスメソッド様 にご支援頂いております。 どのように使っているか? AWSを採用して2年になります。 新規サービスはAWS 稼働中のシステムの半分以上はAWS 今後も継続されるサービスもEOSLを迎えるタイミングで移行 スパイクするアクセスのデータ処理はDynamoDB、イベントトリガーが処理する時はLambda、Push通知はSNS、データ集計はRedshift、操作ログ保存ではGlacierといったような、サービス毎の特性、仕様に合わせた使い方をしています。 どういった立場で使っているか? プロダクトオーナーがKDDIの場合でも、medibaがインフラも含めた技術選定から開発、運用までシステムオーナーとして利用しています。 ここからディスカッションテーマになり、私が発言した部分について補足を加えて記載します。 導入後どうなりました?どんな変化がありましたか? 導入後は、アプリ開発の時間軸にインフラがついてこれるようになったのでアジリティが圧倒的に向上しましたし、キャパシティを柔軟に変更できるため読めないトラフィックによるビジネスへの制約を最小限に抑えることができるようになってきたと思います。 また、オンプレですとコストの制約から環境が貧弱だったり、節約のために相乗りさせてごった煮サーバができたりということもありましたし、リリース以降は商用の環境を再現することはできなかったのですが、開発の状況に応じて開発環境を柔軟に作り変えられることができることも非常に大きなメリットです。 では次は?(次へ取り組みことは?) インフラチームのリソースも限られており、AWSにおいてはアプリエンジニア主導で進めてきました。AWSを中心としたクラウドによる技術的な変化もそうですし、フロントエンドもかなり技術的な変化が大きく、サービスを多く抱える弊社では、全員がフルスタックを目指すのは限界が見えているので、分業制を敷き、クラウド専任部隊を作り、ナレッジ、ノウハウを集約しクラウド専任メンバーをPJにアサインしていく組織として推進し始めました。 (専任部隊を置くことが、厳密なタスクの線引をしていくというよりも、どこに専門性を置くかということで、サッカーでのチームプレーに例えるとDFも時には攻め上がりますし、FWも前線からディフェンスもするように、専門的なところに主軸を置きそこだけに縛られずチームの状況に応じて業務を進めていくことを目指しています) コミュニティが自分や社内に与えた影響 弊社メンバーもJAWSにお世話になっており、そこの空気感とか勢いを社内に持ち込んでくれてまして、社内の情報共有の活性化にも繋がりましたし、また社外への貢献していく姿勢ができ、ブログも始めるきっかけにもなりました。 何よりもコミュニティへの参加は楽しいですし、いい刺激になりますね。 最後に medibaでは、今後もAWSに注力していきます。また、AWSだけでなく新しい技術を積極的に取り入れ、多くのお客様にご利用して頂けるサービスを提供していきます。 今回お話したAWSをメインにしたクラウドチーム、それ以外にもauサービス、新規サービス、広告システムと様々ポジションでエンジニアを募集しています。 ご興味がある方は、 募集ページ から応募してしてください。 面談という形で情報交換をするのでも大歓迎です。
こんにちは。medibaのauスマートパス開発部の小川です。 最近業務でAndroidアプリ開発を行っておりまして、(今更ですが)Drawerlayoutを加工する機会がありました。 その際に、簡単に出来そうなのに実装してみると悩んだ箇所をまとめてみようとか思います。 ちなみにNavigationViewを使ってはいるのですが主にtoolbarとDrawerlayoutへのカスタマイズの話になりますので、マテリアルデザインの話は出てきません。 NavigationViewは2015/5にAndroid Design Support Libraryに追加された機能で、これを使う事と今まで自分でRelativeLayoutをListViewにaddHeaderViewしていた実装を手軽に書く事が出来て便利なのですが、今回はそれより前段の話になります。 今回出てくるお話 概要 before after 変更箇所 toolbarの位置を上から下に変更(色も変更) DrawerButtonを変更 Drawerが閉じた時に開くボタン(ドロイド君アイコン)を表示 コードについて Android Studio(v1.5.1)のNavigation Drawew Activityの自動生成ファイルに対し、修正を行った箇所のみを記載しています。 メインコンテンツのWebViewの挿入はbefore,afterともにonCreate内で実施しています。 詳細 1.toolbarの位置を上から下に変更 デザインとしてはAndroidアプリっぽさが薄れますが、要件によっては下に持って行く必要に迫られる時もあります(した)。 app_bar_main.xmlのtoolbar周りの箇所 <!-- MainActivity用のlayout--> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/myWebView" android:layout_width="match_parent" android:layout_height="524dp"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="68dp" android:src="@android:drawable/ic_dialog_info" android:layout_above="@+id/custom_toolbar" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_gravity="left|bottom"/> </FrameLayout> <android.support.v7.widget.Toolbar android:id="@+id/custom_toolbar" android:background="@android:color/darker_gray" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:popupTheme="@style/AppTheme.PopupOverlay" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> </android.support.v7.widget.Toolbar> </LinearLayout> </android.support.design.widget.AppBarLayout> こちら、xmlにてLinearLayoutで上下2段に区切ったのち、上段をFrameLayoutで括ったWebViewとFloatingActionButton、下段をToolbarとする事で Toolberを下部に移動させています。 Toolbarは他のViewと同様に扱う事が可能です。 2.DrawerButtonを変更 デザインとしてはAndroidアプリっぽさが薄れますが、要件によっては左上の「開く」ボタン(3本線アイコン)を配置場所、デザインともに変更する必要があります(した)。 今回はDrawerボタンを3本線アイコンからFloatingActionButton(画面左下に浮いている丸いボタン)に変更してみました。 MainActivity.javaのonCreateメソッド内にて // FloatingActionButtonを新たに追加 fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { // クリック時の挙動を追加 @Override public void onClick(View view) { // 追加したいImageViewを生成 iv = new ImageView(MainActivity.this); iv.setImageResource(R.mipmap.ic_launcher); // 追加したImageViewの位置を指定 iv.setScaleType(ImageView.ScaleType.FIT_END); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(android.widget.FrameLayout.LayoutParams.WRAP_CONTENT, android.widget.FrameLayout.LayoutParams.WRAP_CONTENT); lp.topMargin = 1200; lp.leftMargin = 850; addContentView(iv, lp); // 初期は非表示に変更 iv.setVisibility(View.GONE); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); // クリック時のイベントにドロワーメニューの開閉を追加 if (drawer.isDrawerOpen(GravityCompat.START)) { // ドロワーメニューが開いた際に閉じる画像を非表示にする iv.setVisibility(View.GONE); drawer.closeDrawer(GravityCompat.START); } else { drawer.openDrawer(GravityCompat.START); // ドロワーメニューが開いた際に閉じる画像を表示する iv.setVisibility(View.VISIBLE); } } }); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) { @Override public void onDrawerClosed(View drawerView) { iv.setVisibility(View.GONE); } @Override public void onDrawerOpened(View drawerView) { iv.setVisibility(View.VISIBLE); } }; drawer.setDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); // ドロワー開くボタン(三本線)を非表示 toggle.setDrawerIndicatorEnabled(false); 簡単に解説をしますと、 FloatingActionButtonに対しsetOnClickListenerを設定します。 そしてそこでOverrideするonCkickにてDrawerのOPEN,CLOSEを実行するようにします。 また下部でActionBarDrawerToggleとDrawerを紐付けているのはDrawerの状態を取得するonDrawerClosed,onDrawerOpenedを取得したかったためです。 表示上は不要なのでsetDrawerIndicatorEnabledにて3本線アイコンを非表示にします。 3.Drawerが閉じた時に開くボタンを表示 Drawerが画面を覆った際は、グレーアウトした画面右側の覆われていない箇所をタップするとDrawerが再度閉じます。 Drawer自体は既に多くのアプリに取り入れられていますので、UIとしてはかなりメジャーになっていますが 要件によっては明示的に閉じるボタンを表示させる必要があります(した)。 今回はドロイド君アイコンを、Drawarが閉じた際のみDrawarと同じ明るさでグレーアウト箇所右下に表示させています。 コードは↑のMainActivity.javaと共通していますのでそちらをご参照ください。 ここは何でつまづいたか言いますと、まず閉じるボタンをどこに定義するのが良いのかがわかりませんでした。。 予めlayoutファイルに記載しておくと、Drawerが開のいたタイミングでグレーアウトの中に入ってしまします。 かといってDrawerの中に入れると閉じるボタンの意味が半減してしまいます。 下のレイヤーはグレーアウトしつつ、欲しい画像のみ一番上のレイヤーに明るく表示する事が必要でした。 ということで、ここではonClick時に閉じるボタン用のViewを作成しています。 また、Drawerの状態変化に応じて (開→閉)の時→ボタンを表示 (閉→開)の時→ボタンを非表示 と切り替えています。 もう少し細かくDrawerの挙動ステータスを管理すれば、Drawerが動き始めた瞬間に表示を切り替える事も可能です。 感想 今更ながらのDrawerlayoutなのですが細かい部分は都度試行錯誤になりますので、今回に関してももっと綺麗に出来る部分があるのではないかと思います。 基本的には Googleが推奨しているデザイン を踏襲しながらサービス独自のデザインを実現するためには、何が簡単に出来て何が難しいのかを判断をできる様にしておく事が大切だと今更ながらに思います。
こんにちは、インフラストラクチャー部の沼沢です。 AWS の DNS フェイルオーバーの設定についての記事はたくさん出回っていますが、今回は Sorry ページに特化した設定をご紹介します。 以前、社内で AWS 上にシステム構築していた際に、例えば「急激なアクセス増で AutoScaling が間に合わないなどでユーザのリクエストに対して正常に応答できない状態に陥ってしまった時に “画面が真っ白な状態が続くこと” だけは避けたい」という要望を受け、最終手段的な位置付けで構築した Sorry ページ表示の仕組みについてご紹介させていただきます。 特段目新しい技術や情報ではありませんが、AWS にてサーバレスで高可用性な Sorry ページを構築する方法の参考になればと思います。 DNSフェイルオーバーとは? そもそも、DNS フェイルオーバーとはなんなのかを軽くご説明させていただきます。 ※DNS 自体の突っ込んだ説明はしませんので、ご了承ください。 DNS は、例えば example.com = xxx.xxx.xxx.xxx (Web サーバの IP アドレス) というように、"ドメイン名" と “実体サーバの IP アドレスなど” を紐付けています。 この時に、"xxx.xxx.xxx.xxx (Web サーバ)“ になんらかの問題が生じ、サービスを継続できない状態に陥った場合に、 example.com = yyy.yyy.yyy.yyy (別のサーバの IP アドレス) に自動で変更する仕組みを DNS フェイルオーバー と呼びます。 つまり、とあるドメインへのリクエストを受けているサーバなどで何か問題が生じた場合に、 ドメイン名は変更せずに、そのドメインへのリクエストを受ける先を変更する仕組み のことを言います。 AWS の Route53 には、この仕組みが予め用意されており、画面からポチポチするだけで DNS フェイルオーバーを簡単に設定できるようになっています。 サーバレスで高可用性な Sorry ページの仕組み では本題です。AWS の DNS フェイルオーバー機能を利用し、サーバレスな Sorry ページを構築します。まずは図で見ていただくとわかりやすいと思いますので、以下の構成図をご覧ください。 上図に記載の通り、AWS のサービスは以下を利用しています。 Route53 ELB + EC2など (サービス本体のシステム) CloudFront + S3 (Sorry ページのシステム) Route53 が ELB のヘルスチェックのステータスを確認し、ELB が正常と判断している時には ELB 側のレコード情報を、ELB のヘルスチェックで異常と判断されている時には DNS フェイルオーバーが発動し、CloudFront 側のレコード情報を、それぞれアクセス元に返します。 この構成のメリットとデメリット メリット ・サーバレス 今回のメインのメリットです。サーバレス=自分たちで管理・保守するサーバは存在しません。S3 や CloudFront が動いているサーバの管理・保守は AWS に丸投げできます。 = EC2 で構築する場合よりも、運用コストを大幅に削減できます。 ・高可用性 Sorry ページの HTML 自体は S3 に配置してあり、それを CloudFront でキャッシュさせて表示させるため、 サーバレスな Sorry ページ のシステムとなっています。 CloudFront, S3 の SLA は 99.9%以上 であり、高い可用性を簡単に実現できます。 ・正常時は Sorry ページシステムの維持費がほぼ0 本構成では、Sorry ページのために利用しているAWSのサービスは、 CloudFront と S3 の2つで、これらの料金体系は以下の通りです。(2016年2月現在) CloudFront データ転送量に対しての課金のみ -> 正常時はデータ転送が発生しないので $0 S3 データ保存容量に対しての課金 -> 最高値でも $0.033 データ転送量に対しての課金 -> In は全て $0 、Out は CloudFront への転送は全て $0 GET リクエストに対して課金 -> 正常時は GET リクエストも発生しないので $0 つまり、正常時の Sorry ページシステムだけのコストとしては、 $0.033 だけということになります。 デメリット ・Alias レコードは TTL を変更できない A レコードの Alias で ELB, CloudFront, S3 の何れかを指定した場合、TTL は 60 秒となり、こちらでは変更できません。 そのため、DNS フェイルオーバーが発動する前に、 最大で 1 分間は、絶賛障害発生中の ELB 側にトラフィックが流れてしまう ことに留意しなければなりません。 正確には、ELB が各インスタンスへのヘルスチェックで全台を Unhealthy と判定するまでの時間もプラスされます。 この間だけは、"画面が真っ白な状態” となってしまいますので、サービスの SLA 等をご確認の上、導入する必要があります。 各サービスの設定詳細 では、各AWSサービスの設定について、個々に解説していきます。 ELB + EC2 など (サービス本体のシステム) ELBやその配下のインスタンス等には、特別な設定は一切不要です。 S3(Sorry ページ置き場) S3 では以下の対応を行います。 Sorry ページ用の Bucket を作成 Bucket 名の決まりは特にありません 必ず Sorry ページだけのための S3 Bucket を作成してください (後述) Sorry ページの HTML を Bucket 直下に配置して Publish(公開)する クローラー対策として、以下の内容の robots.txt を Bucket 直下に配置して Publish(公開)する User-agent: * Disallow: / 以下の様な状態になっていればOK。 CloudFront(Sorry ページのキャッシュなど) 次に CloudFront です。 CloudFront では、以下の設定を行っていきます。 新規の CloudFront Distribution を作成 Sorry ページ用の Bucket を Origin に指定 [Alternate Domain Names] に、サービスのドメイン名を指定 今回は “dns-fo.mediba-lab.net” というドメイン名で設定し、設定後検証を行います。 作成した Distribution を選択し、[Error Pages] タブを選択 → [Create Custom Error Response] でカスタムエラーページを以下の通り定義 [HTTP Error Code] 403: Forbidden バックエンド(本構成の場合は S3)からのレスポンスコードが 403 の場合 [Error Caching Minimum TTL] 300 エラーを 300 秒キャッシュする [Customize Error Response] Yes レスポンスをカスタマイズする [Response Page Path] /sorry.html S3 の Sorry ページ HTML へのパス [HTTP Response Code] 503: Service Unavailable ステータスコード 503 でレスポンスする 上記を図で表すと以下の様なイメージです。 こうすることで、本体サイトのどんな URL でアクセスが来ても、Sorry ページを返却することが可能です。 また、Google などのクローラーに対しても 503 を返せるため、一時的なものであると認識させる事ができます。 この仕組の実現のために、前述した Sorry ページだけのための S3 Bucket が必要 となります。 実際に作成した CloudFront のドメインにアクセスすると、どんな URL をリクエストしても、503 で Sorry ページが返ってくることが確認できます。 Route53(DNS フェイルオーバー) 最後に今回のキモ、Route53 で DNSフェイルオーバーを設定します。 正常時のレコードを登録 以下のキャプチャのイメージで、A レコードの Alias で本体サービス側の ELB を指定 [Routing Policy] Failover DNS フェイルオーバーを利用 [Failover Record Type] Primary このレコードが Primary であると定義 [Set ID] Primary 任意の値 [Evaluate Target Health] Yes Alias(ELB)のヘルスチェックを利用する [Associate with Health Check] No 予め定義してあるヘルスチェックの利用有無 今回は ELB のヘルスチェックを利用するようしたので、No を選択 フェイルオーバー先のレコードを登録 以下のキャプチャのイメージで、A レコードの Alias で Sorry ページ用に作成した CloudFront を指定 [Routing Policy] Failover DNS フェイルオーバーを利用 [Failover Record Type] Secondary このレコードが Secondary であると定義 [Set ID] Secondary 任意の値 [Evaluate Target Health] No Alias に CloudFront を指定した場合は、No 固定 [Associate with Health Check] No Secondary 側なので、特にヘルスチェックは入れない 以上の設定で、DNS フェイルオーバーを利用した Sorry ページ対応が完了です。 動作検証 では、最後にこの設定がちゃんと動作するか確認してみます。 正常稼働状態の確認 予め用意してあったトップページ、exmaple ページがステータスコード 200 で正常に表示できました。 DNS フェイルオーバーの確認 では、EC2 上で起動している Apache を停止して、ELB 配下にインスタンスが1台もいない状態を作り、大規模障害が発生したと仮定しましょう。 [ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd stop Stopping httpd: [ OK ] Apache 停止直後は、ELB が 504 を返してきています。 その後、数十秒程度で ELB が 503 を返すようになりました。 さらにその後、待つこと 1 〜 2 分程度で、S3 に置いた Sorry ページが表示されるようになりました! ステータスコードもしっかり 503 になっています。 DNS フェイルバックの確認 最後に、EC2 上で停止中の Apache を起動して、ELB 配下にインスタンスが存在する状態を作り、サービスが復旧したと仮定しましょう。 [ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd start Starting httpd: [ OK ] Apache 起動後、同じく 1 〜 2 分程度で正常系のページが返ってくることが確認できます。 まとめ いかがだったでしょうか。この仕組みを自前で全て構築することを考えた場合に想定されるインフラコストや工数を考えると、かなりのコスト削減&開発期間の短縮に繋がるのではないでしょうか。 また、今回の構成はサーバレスというところが一番のキモで、サービスがリリースされた後の運用面のコストも大幅に削減できると考えています。 少々長くなってしまいましたが、Sorry ページに高可用性を求めている方々の参考になれば幸いです。
こんにちは。制作部デザイナーの斉藤です。 私の所属しているチームで約1年前から「デザインスプリント」が導入されました。 当時、セミナーなどで聞くようになったデザインスプリント。 短期間で効率的にアイデアがでてすごくいいらしい!との事なので、medibaでも実践してみることにしました。 「でも結構プロセス多いけど、本当に効率化するのかな?」と半身半疑でした。 初期段階のとりあえずやってみよう!というお試し期間を経て、現時点でまだ業務に最適なやり方を模索中ですが、今回は弊社で行っているプロセスをご紹介いたします。 デザインスプリントとは? Googleのベンチャー機関Google Venturesが、投資先に行っているフレームワークで、5日間かけて効率的、かつ高速にプロトタイピングと検証を行う方法論のこと。 詳細については以下をご覧ください。 Design Sprint ガイドブック v2 from Takaaki Umada 参照: THE DESIGN SPRINT 通常の工程はこちら Day0…Preapre(準備する) Day1…Understand(理解する) Day2…Diverge(発散する) Day3…Decide(決める) Day4…Prototype(試作する) Day5…Validate(検証する) 現在実施中のデザインスプリント(短縮版)の流れ 新サービス立ち上げやアプリ開発などはフルで実施するのが望ましいですが、普段私が担当しているランディングページなどページ数が少ないものでは結構な拘束時間となるので、通常5日間のプロセスをかなり短縮し約2日間に分けて行っています。 Day0 Preapre(準備する) 参加メンバーを決める(ディレクター・デザイナー・エンジニア)。 できればプロジェクトに全く関係ない人物やにも参加してもらうのも良いです。 ※制作内容・仕様書などはあらかじめディレクターに準備してもらいます。 必要な道具:コピー用紙、人数分のマジック、ホワイトボード、付箋 Day1 Understand(理解する)/ Diverge(発散する)/ Decide(決める) この3工程を1時間くらいで一気に進めてしまいます。 Understand(理解する) ファシリテーターの進行の元、目的(課題)とターゲットユーザーがどんな人物か具体的に考え、年齢・性別・趣味・目的などを挙げ、詳細なユーザーのペルソナを想像していきます。 そこからユーザーストーリー(4コマ漫画)を書記役の人がホワイトボードに書いていきます。 4コマ漫画について 本来カスタマージャーニーマップなど作成してユーザー動線やストーリーを検証するのが一般的ですが、簡略版のため簡単にみんなが理解しやすいように4コマ漫画にしています。 ここでのポイントは、漫画の面白さでなく、ユーザー体験としてどれが理想かをみんなで認識合わせするのが大事です。 この時は食べ物系特集のアイデア出しだったのですが、男女問わず幅広い年齢層で、美味しいもの好きな人に関心を持ってもらい、同僚に薦めたくなる様な内容を考えました。 Diverge(発散する) 前項で考えた内容を元に、サービスの目的はどうしたら達成されるかアイデアを出します。 通常は8つ捻出するのですが(これがなかなかツライ)、短縮版なので6つにしています。 1案あたり30秒 + インターバル10秒という短時間にアイデアを振り絞ります。 時間に制限があって焦りますが、追い込む事によって思いもよらないアイデアが出る事が多いです。 すべての案を書き終わった後、それぞれ補足説明をしていきます。 他の人の意外なアイディアも聞けるので個人的にはこの工程が一番楽しいです! Decide(決める) サイレント投票(おしゃべり禁止)は厳守です。 ターゲットユーザー・ストーリーとの整合性を確認しながらこれは!という案にペンでチェックを入れる、もしくはシールを貼って1人3つまで投票し、最も数の多かった案を採用します。 この特集の時は 高級感をだす 季節感のある背景をつかう 食材写真を背景にならべる 湯気、炎で美味しそうな効果をつける 人物が美味しそうに食べている写真をつかう おしゃれな雑誌風の写真をメインにつかう などいろいろなアイデアが集まりました。 最終的に一番票を集めたのは、おしゃれな写真をメインに使った、雑誌dancyuのようなイメージの案でした。 Day2 Prototype(試作する) ここからはデザイナーが単独で作業に入ります。 前回決まった案を元に、まずはラフ(手書きでも、デジタルでもイメージ伝わればOK)で プロトタイプを試作し、関係者に展開します。 Prott 、 POP などのプロトタイピングツールを使って実機でも確認します。 なお、ここでお互いにイメージや認識の違いがあった場合は随時調整します。 ラフが完成したら実際のデザイン作業に移り、完成を目指します! もうちょっと時間に余裕のある場合はこの後に Validate(検証する) という工程するのですが、現状なかなか実施できていません。 Validate(検証する)の工程はこんな感じです。 プロトタイプを作成した人が、カンタンに動作説明をする 全員でプロトタイプを触る ターゲットユーザーに近い、第3者に入ってもらうと更に良い Good or Request を3分間(案件によって可変)、付箋に記入 ホワイトボードに貼っていく グルーピングする Requestをどう取り入れるか議論し、本制作に入る 問題や課題が出てきたら、アイディア出し/試作の工程に戻って繰り返す Good or Requestというのは「いいと思うところ」と「こうしたらもっと良いかも」を付箋に書いて貼っていくフローです。(こちらは以前実施した時の様子) まとめ デザインスプリント導入前は、打ち合わせ1回目でメンバー全員の意識合わせが難しく、お互い認識の微妙なズレが生じてしまい、リテイク、もしくは作り直しが起こるという悪循環がしばしばありました。 デザインスプリントをやってよかったのは、プロジェクトに関わるメンバーでアイデアを出すことで閉鎖的にならず、決定も素早く、みんなで作ったという連帯感やプロジェクトに対する愛着が生まれる点だと思います。 さらに、今まで見えずらかったユーザーの姿がより具体的になる事で、情報がユーザーに届く精度もあがるのも素晴らしい点と言えるでしょう。 本来、プロトタイプ完成後にペルソナに近いユーザーテストをするのですが、現状できておりません。 しかし、ユーザーテストをすることで、さらに興味深い発見があったり、違った課題が見えると思うので、ぜひフローに加えて改良していきたいと思います。
こんにちは。制作部フロントエンジニアの苅部です。 GoogleからCloud Vision APIの提供が始まっていたので、スマートフォンのカメラから利用できるモック画面を作って、APIの画像認識精度を試してみました。 簡単ではありますが、HerokuでのNode.js利用のおさらいと、実際にいくつかの画像を送信した結果を共有できたらと思います。 (Cloud Vision APIは2/18日に 公開ベータ になっています) Cloud Vision APIとは GoogleフォトやSafeSearchで採用されている、Googleの機械学習の画像認識APIです。 画像を載せてAPIコールすることで以下の情報の取得が可能です。 物体検知 OCR 有害コンテンツ検知 顔検知 ロゴ検知 ランドマーク検知 HerokuでのNode.js利用までの流れ APIKEY取得からAPIコールおよび画面実装までの流れをご説明します。 今回は以下の要件で実装しています。 WEBサーバー: Node.js/Express4(Jade) プラットフォーム: Heroku クライアント: jQuery UIパーツ: OnsenUI WEBサーバー側もJavaScriptを利用しているので、フロントエンジニアの方ならDOM操作とちょっとしたAPIの仕様把握だけで短時間で実装ができると思います。 1. Developer Consoleへの登録・APIKEYの取得 GoogleのAPIを利用するにあたり、まずはDeveloper登録が必要になります。 1) GoogleのDeveloperアカウントを持っていない場合は取得します。 https://console.developers.google.com/ 2) 上記DeveloperConsoleからAPIKEY(サーバーKEY)を取得しておきます。 3) 以下URLからdocumentationの閲覧ができます。 https://cloud.google.com/vision/docs/ 2. Herokuへの登録と準備 Node.jsが利用可能で、ドメインも発行されるHerokuをプラットフォームとして選択しました。 MongoDBも簡単に扱う事ができますし、スピード感をもってモック作成するには最適なサービスだと思います。 ・ユーザー登録 Herokuのアカウントを持っていなければ登録します。 https://www.heroku.com/ ・Heroku Tool Beltをインストール Herokuをコマンドラインから利用できるようにします。 https://toolbelt.heroku.com/ ・Herokuへログイン $ heroku login 認証を求められるので、Herokuのid/passを入力してログインします。 ・Gitリポジトリの作成 $ cd my-project/ $ git init $ heroku git:remote -a [projectName] ・Procfileの作成 Procfileという名前で、プロセスの定義ファイルをプロジェクトルートに配置します。 今回の場合 Nodeでapp.jsというファイル扱うため、以下のような内容で設定しています。 node app.js 以上でHerokuを利用する準備が整いました。 3. Node.js側の実装 WEBフレームワークは Express/Jade を利用しています。 Node.jsのスクリプトは以下のような内容で[app.js]としました。 var express = require('express'); var bodyParser = require('body-parser'); var request = require('request'); var app = express(); var server = app.listen(process.env.PORT || 3000, function () { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); }); app.set('view engine', 'jade'); app.set('views', __dirname + '/views'); app.use(express.static(__dirname + '/public')); app.use(bodyParser.urlencoded({extended: false, jsonLimit: '3000kb'})); app.get('/', function (req, res) { res.render('index', { title: 'Cloud Vision API Test App' }); }); app.post('/api/cloudvision',function(req,res){ var image = req.body.image.match(/base64,(.*)$/)[1]; var reuestOption = { uri: 'https://vision.googleapis.com/v1/images:annotate?key=[APIKEY]', headers: {'Content-Type': 'application/json'}, json:{ "requests":[ { "image":{"content": image}, "features":[ {"type": "FACE_DETECTION", "maxResults": 5}, {"type": "LABEL_DETECTION", "maxResults": 5}, {"type": "TEXT_DETECTION", "maxResults": 5}, {"type": "LANDMARK_DETECTION", "maxResults": 5}, {"type": "LOGO_DETECTION", "maxResults": 5}, {"type": "SAFE_SEARCH_DETECTION", "maxResults": 5} ] } ] } }; request.post(reuestOption, function (error, response, body) { if (!error && response.statusCode == 200) { res.status(200).json(body.responses) }else{ res.status(200).json({ status: 'err' }) } }); }); — 補足 — jsonLimit: ‘3000kb’ bodyparserのデフォルト値が1MBのため、3MBへ増やしています。 ※ 画像認識の精度を上げるため可能な限り解像度は高い方が良さそうです。 ※ GoogleのAPI側では8MB/request,2MB/imageの制限がかかっています。 requestOptions.uri APIキー[サーバーキー]を含めたGoogle側エンドポイントです。 ※限定プレビューと公開ベータではURIが若干異なります。 requestOptions.json.requests.image base64エンコードした画像です。 requestOptions.json.requests.features 必要になる画像認識機能と件数を任意で設定します。 request.post() requestモジュールを使いGoogleへPOSTリクエストします。 4. クライアント側の実装 Node.js側で設定したURL[/api/cloudvision]に、画像を載せる形でPOSTリクエストを行い、レスポンスのJSONデータを整えて画面に表示します。 コードの記述は省略しますが、実装の要点は以下のようになります。 1) inputタグのaccept属性にcapture=cameraを追加する事で、モバイルブラウザでもカメラ/カメラロールから画像取り込みができるようになります。 <input type="file" accept="image/*;capture=camera"> 2) 取り込まれた画像をリサイズ/圧縮するために(2MB以内に抑えるために)jQueryプラグインを利用しました。 https://github.com/gokercebeci/canvasResize ユーザーがスライダーUIを操作することで、任意で画質のレベル調整ができます。 $('.input-range').change(function(){ var file = $('input[type=file]')[0].files[0] compressImage(file) }) function compressImage(file){ var compressLevel = Number($('.range').val()); $.canvasResize(file, { width: 610, height: 0, crop: false, quality: compressLevel, callback: function(data, width, height) { $(".image-preview").attr('src', data); } }); } 3) UIはOnsenUIを利用しています。(ボタンやスライダーの見た目を整えます) 5.アプリケーションのデプロイ リモート環境にアプリケーションをPUSHして、デプロイします。 $ git add . $ git commit -am "make it better" $ git push heroku master アプリケーションを動かす上で最低限必要なファイルは以下のようになります。 (staticなファイルは除く) ├── Procfile ├── app.js ├── package.json └── views └── index.jade 画面の表示 デプロイが完了したので画面を確認してみます。 iOSではカメラ/カメラロールから添付できることがわかります。 PCであればコマンドラインでブラウザを立ち上げ、アプリケーションを表示する事もできます。 $ heroku open 実際にリクエストを投げてみた結果 では早速手持ちの写真を送信して、Googleが画像をどのように認識しているか試してみます。 ※ ここで表示しているのはサムネイルですので、実際に送信している画像とは解像度や画質が異なります。 ※ レスポンスのJSONは見やすくするため、一部の値を削除しています。 Face Annotations (顔検知) 被写体がどういった表情をしているか、顔のパーツがどこにあるか、といった情報が取得できます。 Image Response “joyLikelihood”: “VERY_LIKELY” , “sorrowLikelihood”: “VERY_UNLIKELY”, “angerLikelihood”: “VERY_UNLIKELY”, “surpriseLikelihood”: “VERY_UNLIKELY”, “underExposedLikelihood”: “VERY_UNLIKELY”, “blurredLikelihood”: “VERY_UNLIKELY”, “headwearLikelihood”: “VERY_UNLIKELY” joyLikelihoodが"VERY_LIKELY"で返っていて、[楽しんでいる]という事が認識できています。 Text Annotations (OCR) 画像に写り込んでいる文字情報について、内容を抽出したり言語判定したりすることができます。 Image Response “textAnnotations”: [{ “locale”: “en”, “description”: “ ABOUT LIFE\n COFFEE BREWERS\n 1-19-8 DOGENZAKA SHIBUYA\n TOKYO JAPAN 150-0043\n TEL 070-5587-5342\n OPEN EVERYDAY 8:30-20:30\n www.about-life.coffee \n ”}] 誤りの無い文字情報が取得できました。 Label Annotations (物体検知) 物体の情報(ラベル)を、数千ものカテゴリの中から分類ができます。 Image Response “labelAnnotations”: [{ “description”: “ auto show ”, “score”: 0.99762589}], “labelAnnotations”: [{ “description”: “ ferrari f430 ”, “score”: 0.997009}] “labelAnnotations”: [{ “description”: “ sunflower ”, “score”: 0.97045457}] “labelAnnotations”:[{ “description”: “ hydrangea ”, “score”: 0.97828537}], “labelAnnotations”: [{ “description”: “ cyclo cross ”, “score”: 0.98051214 }, { “description”: “ cyclo cross bicycle ”, “score”: 0.96340382}], 1枚目の写真では自動車に限らず、[auto show]ということまで認識できました。 2枚目の写真はFerrariだけではなくF430という車種まで認識しました。 3,4枚目では花の種類をしっかり認識しています。 5枚目は自転車だけではなく、[シクロクロス]というところまで認識しました。 この画像でシクロクロスと認識できるのは、なかなか人間の知能に近いように思えます。 Logo Annotations (ロゴ検知) 商品や企業のロゴを検知できます。 Image Response “logoAnnotations”: [{ “description”: “ Lamborghini ”, “score”: 0.3002826, “boundingPoly”: { “vertices”: [{“x”: 72,“y”: 124}, {“x”: 105,“y”: 124}, {“x”: 105,“y”: 161}, {“x”: 72,“y”: 161}]} }], 車体の後方に映っているランボルギーニの猛牛のロゴが認識されました。 ※boundingPolyで位置の特定が可能です。 Landmark Annotations (ランドマーク検知) 自然構造物や位置情報の取得が可能です。 今回は位置情報が返却された画像のみをピックアップしました。 Image Response “description”: “Brooklyn Bridge” , “locations”: [{ “latLng”: { “latitude”: 40.705726, “longitude”: -73.996953}}] GoogleMap “description”: “ Broadway ”, “locations”: [{ “latLng”: { “latitude”: 40.783708, “longitude”: -73.97948}}] GoogleMap “description”: “ BFI Southbank ”, “locations”: [{ “latLng”: { “latitude”: 51.507032, “longitude”: -0.115935}}] GoogleMap “description”: “ Brick Lane ”, “locations”: [{ “latLng”: { “latitude”: 51.520466, “longitude”: -0.071496}}] GoogleMap “description”: “ Camden Lock ”, “locations”: [{ “latLng”: { “latitude”: 51.541274, “longitude”: -0.145536}}] GoogleMap “description”: “ Trellick Tower ”, “locations”:[{ “latLng”: { “latitude”: 51.523163, “longitude”: -0.205928}}] GoogleMap “description”: “ Nagawado Dam ”, “locations”: [{ “latLng”: { “latitude”: 36.132087, “longitude”: 137.719245}}] GoogleMap “description”: “ Hyōgo Prefectural Museum of Art ”, “locations”: [{ “latLng”: {“latitude”: 34.699125099999996, “longitude”: 135.218491}}] GoogleMap “description”: “ Consolidated city-county ”, “locations”: [{ “latLng”: { “latitude”: 35.688879, “longitude”: 139.69056129455566}}] GoogleMap “description”: “Haneda Airport” , “score”: 0.36270857, “locations”: [{“latLng”: { “latitude”: 35.578347, “longitude”: 139.784348} }] GoogleMap “description”: “ Tokyo Bay Aqua-Line ”, “locations”: [{ “latLng”: { “latitude”: 35.463999, “longitude”: 139.874554}}] GoogleMap どの写真でもDescriptionと位置情報が正確に返却されています。 ※アップロードした画像には位置情報に関するEXIFは含まれていません。 2枚目の写真はNYのBanksyのグラフィティですが、Googleは位置情報を正確に理解しているようです。 (GoogleMapのストリートビューでもグラフィティが確認できます) 3,4枚目はロンドンのグラフィティになりますが、これだけの写真でも理解できるようです。 それ以降の写真でも、無機質なダムの写真だけでも奈川渡ダムと判定されたり、らせん状のコンクリートだけで兵庫県立美術館と認識しました。 飛行機の写真は羽田空港と認識されています。位置情報も実際に撮影した場所から近く、どういったロジックなのかとても不思議です。 最後は、夜間の暗い写真ですがアクアラインとして認識される事が可能でした。 もしかすると、Googleは世の中に散らばっている画像やそれに含まれるEXIFの位置情報を照らし合わせて機械学習しているのかもしれません。 もしそうであれば 同じような構図が多く、位置情報が残るデジカメやスマートフォンで撮られているような写真(構図)が、ランドマーク(位置情報)検知されやすいのかも、、しれません。 まとめ 特徴的なレスポンスが返された画像だけを今回ピックアップしましたが、ここまで正確に、細かく認識できるのは驚きました。 RESTで提供されている画像認識APIは他にもMicrosoftの Project Oxford やIBMの Watoson がありますが、物体検知のカテゴリ数や認識精度で比較すると、今の段階ではGoogleの方が一歩進んでる印象があります。 最近Narrative Clip2を購入したのですが、Cloud Vision APIを使って大量の画像データをフィルターしたりなど、いろいろと妄想が膨らみます。 皆様も是非一度、Googleの画像認識のAPIを試してみて、使い道を検討されてはいかがでしょうか!
こんにちは。 mediba メディアシステム開発部の尾野です。 ついにブログを書く日がやって来ました・・・ 良い機会なので、ここ半年くらい気になっていた「Appium」を取り上げてみたいと思います。 ■Appiumとは? http://appium.io/ 概要 Appiumとは、Selenium作者のJason Huggins氏を中心に開発された デバイステスト自動化を実現するためのテストフレームワークです。 Appiumを使えば、実機/エミュレータを使ってEnd To Endテストが出来ます。 仕組み概要 PC上のテストプログラムを実行    ↓     ↑ PC上のAppiumから実機にリクエスト(Mobile JSON Wire Protocol) ※この時UI Automator用のアプリ等を端末に転送    ↓     ↑ 実機で動作 という流れとなってます。 UI AutomatorはAndroid OS 4.2以降(API Level 17以上)の場合です。 (Android OS 4.1以下の場合はSelendroid) テスト対象OS Android : Ver. 2.3.3以降 iOS : Ver. 6.0以降 特徴 実機テストができる 同じAndroidのバージョンでもメーカーによって微妙に挙動が違うことがあります。 その為多くの端末で検証をしなければならずひと苦労・・・ なんて事も多々あるかと思います。 Appiumでは機械的に実機のブラウザをエミュレートしたテスト出来るので、 人手による多端末検証の労力を抑える事が出来ます。 言語選択肢が多い ヘッドレスブラウズE2E(ex.PhantomJS)やrubyのCapybara等、 OSSのE2Eテストソリューションは沢山ありますが、言語の選択は制限されてしまいます。 Appiumでは執筆(2016/02)時点で以下の言語が使えます。 Java PHP Perl Ruby Python C# Javascript(Node.js) クロスプラットフォーム 実行環境はWinでもMacでもLinuxでもOK テスト対象環境は実機でもエミュレーターでもOK (iOSの場合はXcodeが必須なのでMac限定ですが・・・) Selenium WebDriverのナレッジを活かせる 自動E2Eテストの代表格でもある「Selenium」の拡張版、の様なものなので、 今までSeleniumでE2Eテストやってたという方なら入りやすいと思います。 準備 環境とか PC : Max OS X Yosemite(10.10.5) NodeJS v4.2.1 Homebrew経由でインストール Java(OpenJDK) v1.8.0_60 環境変数 JAVA_HOME 設定済み 実機 : Galaxy Note 3 (Android 5.0) テストコード 言語           :Javascript(Node.js) テスティングフレームワーク:mocha アサーション       :chai + assert(node標準) テストレポーター     :mochawesome 実機側設定 開発者向けオプションの「USBデバッグ」を有効にする必要があります。 開発者向けオプションを表示する方法 [設定] -> [一般] -> [端末情報] [ビルド番号]を7回タップすると「これでデベロッパーになりました!」のメッセージが表示され、開発者オプションメニューが表示されます。 USBデバッグを有効にする [設定] -> [一般] -> [開発者向けオプション] [USBデバッグ]にチェックをつける。 テスト実行中にロックが掛からない様にするため、 [スリープモード非設定]にもチェックをつけておいたほうが良いです。 インストール Android Studio ここからインストールします。 http://developer.android.com/intl/ja/sdk/index.html Configure -> SDK Manager -> System Settings -> Android SDK SDK Platformsタブ Android 5.0.1(対象端末が5.0なので) SDK Toolsタブ Android SDK Build Tools Android SDK Tools Android SDK Platform-Tools 環境変数を設定 $ vi ~/.bash_profile export ANDROID_HOME=[[Android Studioインストール先sdkフォルダパス]] export PATH=$PATH:$ANDROID_HOME/platform-tools/:$ANDROID_HOME/tools/ PCと実機をUSBでつないで、「adb devices」コマンドを実行 $ adb devices List of devices attached [[端末のUDID]] device # -> 識別NGの場合「List of devices >attached」と表示 《tips》Emulatorの作成・起動 今回は使用しませんが、Emulatorで動作確認をする場合には以下の手順で作成・起動します。 前述の「adb device」コマンドで作成したEmulatorのUDIDが表示されれば成功です。 $ android avd Android AVD Managerが起動する -> 「create」 $ emulator -avd [[AVD名]] Android Emulatorが起動する Appium インストールには2つの方法があります。 1)githubからgit cloneする https://github.com/appium/appium 2016年2月現在 v1.4.16 [メリット] Ver.はこちらのほうが進んでる ソフトウェアメンテナンスが容易 複数プロセス起動&実行が可能 [デメリット] git clone後のセットアップに時間が掛かる(mavenやantも必要) CUIベースになるのでコマンド使いはじめるまでに学習コストが掛かる インスペクタ(Nativeアプリの要素解析機能)が無い 2)デスクトップアプリをダウンロードする https://bitbucket.org/appium/appium.app/downloads 2016年2月現在 v1.4.13 [メリット] 必要なコンポーネント群が内包されている GUI付属 インスペクタ付属 [デメリット] Ver.はこちらのほうが遅れている 複数起動が出来ない 今回は2)の方法でインストールしたものを使います。 Appium.appを立ち上げるとこんな感じのツールが立ち上がります。 ①・・・各種設定 (左から) Android設定(後述) iOS設定 Appium本体の設定 開発者設定(Node.jsのパス変更等) Robot Framework用設定 ②・・・インスペクタ Nativeアプリの要素解析用ツール ③・・・appium-doctor Appiumが実行可能かどうかを検査してくれるツール 「✔ All Checks were successful」のメッセージが表示されれば実行可能 実行用設定 Android Capabilitiesブロック 「Platform Name」・・・Android 「Automation Name」・・・Appium 「Platform Version」・・・5.0 Lollipop ※Automation NameはAndroid OSのVer.が4.1以下(API Levelが16以下)の 場合に「Selendroid mode」に変更します。 実行 テスト対象 スマートフォン版スマートパスTOPページを対象にテスト実行してみます。 https://auone.jp/ 1)auone.jpにアクセス出来る事 2)正しくログイン出来る事 を検証してみたいと思います。 Appium起動 右上の「Launch」を押下すると・・・ 起動している感じがする・・・ テストコード(一部抜粋) 1)auone.jpにアクセス出来る事 it("TOPページアクセス", function() { return driver .sleep(10000) // 描画完了まで(念のため)時間とっとく // スクショを撮る .saveScreenshot(saveScreenDir + "TOPページアクセス") //ページタイトルが正しいか? .title() .should.eventually.include("auスマートパス"); }); 2)正しくログイン出来る事 it("TOPページからログインしてみる", function() { return driver // ログイン認可Cookie削除 .deleteCookie("【ログイン認可Cookie】") .elementByLinkText("ログイン").click() .sleep(10000) .saveScreenshot(saveScreenDir + "ログイン") // ログイン画面のタイトル検証 .title() .should.eventually.include("au IDログイン") // ID/PW入力 .elementById("loginAliasId").sendKeys("【ログインID】") .elementById("loginAuonePwd").sendKeys("【ログインPW】") .submit() .sleep(10000) .saveScreenshot(saveScreenDir + "[ログイン済]TOPページアクセス") // TOPに戻ってきた事をタイトルで検証 .title() .should.eventually.include("auスマートパス") // 認可Cookieの存在を確認してログイン済か検証 .allCookies() .then(function (cookies) { cookies.length.should.not.equals(0); for (var iii = 0; iii < cookies.length; ++iii) { if (cookies[iii].name === "【ログイン認可Cookie】") { return driver; } } assert.fail("doesn't exists 【ログイン認可Cookie】 cookie."); }) }); テスト実行 以下のコマンドを実行 レポート出力形式にmochawesomeを指定(–reporter mochawesome) レポートオプションに以下を指定 出力先: ./report/html/以下(reportDir=./report/html/) レポートファイル名:auonejp_test_sample(reportName=〜) レポートタイトル:auonejp_test_sampletitle(reportTitle=〜) 一枚完結ページにするか否か:inlineAssets=true $ mocha –reporter mochawesome \ –reporter-options \ “reportDir=./report/html/, reportName=auonejp_test_sample, reportTitle=auonejp_test_sampletitle, inlineAssets=true” \ appium_app_test.js Appiumコンソールにログが出力されています。 端末上のブラウザも起動し、以下の様に画面遷移してます。 テスト完了 テスト結果がターミナル上に表示 スクリーンショットもちゃんと撮れてます。 mochawesomeレポート html形式で出力されます。 テストケース2件とも成功しております。 詳細は以下参照 http://adamgruber.github.io/mochawesome/ 感想 Appiumはまだ触り始めて間もないですが、そこまで導入敷居も高くない様に感じました。 まだまだ実験段階なので、いつかのテスト自動化運用を見据えつつも、 ツールを過信しすぎない程度に継続的な調査をしていきたいと思います。 また、AWS Device Farmとも連携してみたりするともっと世界が広がりそうですね。 https://aws.amazon.com/jp/device-farm/
こんにちは。 2回目の登場になります、auスマートパス開発部の松本です。 多様化、複雑化するデータを使ったサービス開発の需要も高まっており、今回は使用感の調査もかねてグラフデータベースを触ってみました。 使用するデータベースは最もポピュラーであろうneo4jです。 書かれている記事も多く、とりあえず触ってみるのにはちょうどいい感じでした。 neo4jにはCypher (サイファー)というめちゃくちゃカッコイイ名前のクエリ言語があり、WEBインターフェースを使ってダイレクトにデータを処理することができます。 今回、何度も初期化を繰り返しながら試行することになるので、データの作成はRubyとneographyを用いることにしました。 初回ということもあり、データをグラフ化することに焦点を置いています。 LINK * neo4j * neography データを作成する ◼接続の確立 まず、接続を確立します。 require 'rubygems' require 'neography' @suma = Neography::Rest.new("http://ユーザ名:パスワード@localhost:7474") ◼ノードの作成 neographyのgithubのWikiを見ながら、ノードを追加していきます。 今回は特に使いませんが、プロパティには趣味(hobby)を持たせています。 node1 = @suma.create_node(name: "M君", hobby: "Video game") node2 = @suma.create_node(name: "A君", hobby: "surfing" ) ・ ・ ・ プロパティはあとから追加、変更できます。 @suma.set_node_properties(node1, {"hobby" => "FootBall"}) @suma.set_node_properties(node2, {"division" => "DevG"}) ノードを削除するのも簡単です。 @suma.delete_node(node1) ◼ラベルの追加 ここで、nodeのラベルに「Engineer」を追加します。 エンジニアをラベルにするかプロパティにするかちょっと悩みました。 ラベルにした場合   「Engineer」テーブルに各ノードが格納されるイメージ プロパティにした場合   ノードに「職業」という「属性」がつくイメージ この辺りは用途というか設計次第となるのでしょうが、今回は全員がエンジニアであることと後の抽出作業を考えて、ラベルにしました。 @suma.add_label(node1, "Engineer") @suma.add_label(node2, ["Engineer","1G"]) ・ ・ ・ ノードの登録が終わったところで、Cypherを用いてグラフ化してみます。 合計8名がノードとして登録されています。 ◼relationships(関係性)の追加 次に、グラフDBのキモである、 relationships(関係性) の記述を行います。 関係性には方向があります。friendsな関係とはいえ、一方通行でないとは限りません。 node2(A君)はnode1(M君)を友達だと思っているので以下のように記述します。 @suma.create_relationship("friends", node2, node1) この時点では、node2(A君)からnode1(M君)への一方向な関係線が引かれるだけです。 このままでは、友達とは言えません。 node1(M君)も、まあnode2(A君)を友達だと思っているので、引数を逆にして同様の記述を行います。 @suma.create_relationship("friends", node1, node2) グラフで見てみるとこんな感じです。 node1(M君)とnode2(A君)の間に「friends」が双方向で存在しています。 全てのノードに対して、関係性を記述していきます。 最終的にこんな形になりました。 これでデータの準備ができましたので、いろいろ抽出してみます。 データを抽出してみる ここまで作成したデータを用いて、いろいろ抽出してみます。 ◼A君を取り巻く人間関係は? A君の周りの全ての関係性を抽出します。 なかなか複雑ですね。 ◼A君「が」友人だと思っている人は? Aくんから出ている「friends」relationshipsのうち、外向きのものを抽出します。(双方向のrelationshipsを含む) ◼A君「を」友人だと思ってくれている人は? Aくんから出ている「friends」relationshipsのうち、内向きのものを抽出します。(双方向のrelationshipsを含む) 同じ 「friends」 という関係性でも、方向が違えば見え方も変わってきます。 この他に、「友達だと思っている人の友達」や「サッカーが好きな友達」なども抽出することができます。 「関係性」 に 「方向」 が加わることによって、 「friends」 という単語だけでは表しきれない関係が簡単に抽出できているのがわかると思います。 まとめ ほんの少し触っただけですが、「方向を表現できる関係性」を持たせられることがすごく便利でした。 「A君の友達の友達で趣味がサッカーの人を検索せよ」。これを例えばMySQLで実装しようとするとちょっと面倒な事になると思います。 (テンポラリ的な「友達テーブル」を作るとか) ◼︎関係性の表現について 今回はfriendsという単一のrelationshipsで方向のみを用いて関係性を表現しました。 ですが、関係性自体にプロパティを記述できるため、単に「知り合い」というrelationshipsを持たせ、そのプロパティに付き合いの深さを記述するやり方も考えられます。 また、方向性ごとに関係性の名前を変えるというやり方もあると思います。 一方通行:知り合い 双方向:friends! など。 どれが最適なのかは、まだまだ検討をしていく必要がありそうです。 今後は、RDBとの比較などもやってみたいと思います。
こんにちわ、情報システム部 佐藤です。 mediba で提供しているサービスは Amazon AWS のテクノロジ を利用したものが多いのですが、今回は Microsoft Azure を利用して業務系システムのメンテナンスを実施したお話です。 さて、 Azure File Storage が昨年末に一般提供されました。 最大の特徴は SMB 2.1 および SMB 3.0 に対応 していること。 これにより、オンプレからクラウド上の共有フォルダをマウントして利用することが可能です。 Amazon AWS の 場合 S3 バケットを直接マウントしてファイルシステムのように使うツールとして s3fs や goofys などがありますが、ツールを入れるのが躊躇される場合やお手軽に試したい場合に活用されては如何でしょうか? 今回は、PowerShell から Azure File Storage を作成し Windows Server のネットワークドライブとしてマウントして利用するところまでを試します。 準備 Azure アカウントの入手 こちら から入手できます。 PowerShell へのコマンドラインのアップデート こちら からAzure コマンドラインインターフェイスを入手できます。 Azure File Storage の用意 マウントするための共有ディスクを作成します。この作業は PowerShell が入っているクライアント端末であれば実行可能であるため、サーバーとは別の環境であらかじめ実施しておくのがお勧めです。 PowerShell ※ Azure アカウントと紐づけを行います。 PS C:\> Add-AzureAccount ※ サブスクリプションが複数ある場合は固定します。 PS C:\> Select-AzureSubscription -SubscriptionID:'subscriptionid' ※ 作成するストレージアカウントの名前チェックをします。 PS C:\> Test-AzureName -Storage hogehoge 詳細: The storage account named 'hogehoge' is already taken. True ※ True が帰ってくる場合は既に存在するため Flase となる名前を探します。 PS C:\> Test-AzureName -Storage mediba False ※ サブスクリプションで利用可能なロケーションを確認します。 PS C:\> Get-AzureLocation | format-Table -Property Name, storageAccountTypes 詳細: xx:xx:xx - Completed Operation: Get-AzureLocation Name StorageAccountTypes ---- ------------------- East US {Premium_LRS, Standard_LRS, Standard_ZRS, Standard_GRS...} ・・・・ Japan West {Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS...} Japan East {Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS...} ※ 利用可能なロケーションが返ってきます。この中から作成するロケーションを決めます。 PS C:\> New-AzureStorageAccount -StorageAccountName -Location 'location name' ※ 'location name'には先ほどの Japan East などを指定 ※ 作成したストレージアカウントにコンテナを作ります。 PS C:\> Set-AzureSubscription -SubscriptionID:'SubscriptionID' -currentStorageAccount 'アカウント名' PS C:\> New-AzureStorageShare 'コンテナ名' ※ 作成したストレージキーをこの後の処理で使いますので出力してメモなどに保存します。 PS C:\> Get-AzureStorageKey 以上で、Azure 側の準備は完了です。 Windows Server 側での共有ドライブのマウント Azure File Storage をマウントするためにはインターネットに向けて TCP 445 が開放されている必要があります。Range などを絞って開放する場合、 こちら の Microsoft の技術情報を参考にしてください。 コマンドプロンプト ※ 指定のドライブに共有フォルダとしてマウントします。 C:\>Net Use 'ドライブレター:' \\'アカウント名'.file.core.windows.net\'コンテナ名' /u:'アカウント名' 'ストレージキー' 以上で、Windows 側の共有フォルダとしてマウントすることができました。 見た目は、通常の共有ドライブと変わりありません。 Format は MAFS という特殊な 5TB の共有ディスクができあがりました。 使ってみた 作成した共有フォルダに早速ファイルをコピーして速度をチェックしてみます。 其の前にインターネットへのアップロード速度を計測しておきます。 現在の環境の上りの回線速度は以下のとおりでした。 20 Gbyte のファイルを移動してみました。 ほぼ、回線の上限値で推移をしていることがみれます。 約 30 分程度で移動をすることができました。 Japan East のロケーションを選択したからか、思った以上に速度がでます。 巨大なファイルを移動する場合は、帯域に注意が必要です。 まとめ ルーターから外部に向けて TCP 445 が開放されていることを確認しよう。 帯域には注意しよう。 Azure 上の仮想環境でも同様にマウントすることが可能です。 ファイルの仮置き、Azure 仮想環境への簡易移動など、ディスクイメージの退避などいろいろな用途で使ってみてはいかがでしょうか?
こんにちは。mediba制作部の大村です。 2016年1月6日に弊社でパパママ向けキュレーションサイト camily-β版- をオープンいたしました。 camily [キャミリー]|働くママとパパの仕事と育児をもっと自由に そこで制作したサービスロゴを用いて、基礎的な要点を交えロゴタイプの作り方を紹介します。 1. ベースとなるフォントを探す サービスイメージと合うフォントを探す フォントを洗い出したら同じくらいのサイズにして並べ、どれが読みやすいか、狙いと雰囲気が合っているか確認してみましょう。フォントを探すとき留意したい点は サービスイメージと合う ということ。予めサービスの特徴や理念を洗い出し、それを元に考え始めます。 サービス名 camily[キャミリー] ターゲットユーザー(作成当時) 未就学(0〜5歳)の子供を持つ仕事をしているママとパパ 特徴 月齢や年齢に応じて記事を出し分け 理念(サービスの意図) 仕事をしているからこそ出てくる育児の悩みを軽減してもらいたい ※ camily とは carrier[キャリア] と family[ファミリー] を繋げた造語になっており、これらが繋がってバランスが取れていてるイメージ(※課題1)と relief[安心] という意味も込めたい(※課題2)ので優しいイメージを表現したいという課題も。 ポイント 大文字小文字の組み合わせなどでイメージが変わるので、その点も加味して(または活かして)イメージを作成していきましょう。 (今回は先に 全て小文字 でサービス名をFIXしていたので、小文字のみでバランスが良くなるように注意しています。) 2. ロゴの表示サイズを確認 きちんとロゴを見せるために表示サイズを最初に決定する 実際デザインにはめてみると 「読めない!」「見えない!」「見辛い!」 ということが多々有ります。 サービスの対象機種やブラウザを確認し、最小サイズの機種でもきちんと見えるように、また、他のパーツも収まるようにロゴの表示可能領域を 予め確認 しましょう。 (主流と言われている最小サイズ《iPhone 4、4s 3.5インチ(320×480px、Device pixel ratio 2)》を最小とし、 最大シェアの画面サイズは《Galaxy Nexus 5 4.7インチ(360×567px、Device pixel ratio 3)》これをメインに意識します。 Device pixel ratio 3は非常に大きな画像が必要になるため、Webの場合は表示速度が落ちユーザー体験に悪影響を及ぼす可能性があります。 カンプ作成の際には作業効率も考慮しDevice pixel ratio 2(幅720px)に留め制作を進めます。 それを実機で確認できる環境を作り、確認しながらデザイン作成します。 ポイント ロゴを先行で作らなくてはいけない場合は大体のサイズを想定して、後々調整の必要があることをスケジューリングしましょう。 3. 400%にて作成開始 整数値で作成すると滲みの少ない表示になる 端末によってDevice pixel ratioが違うのでピクセルパーフェクトの実現は難しいのですが、極端に太すぎたり細すぎたりしないように実際自分が作りたいイメージを 逆算して作成 します。 整数値の表示になるよう心がけることでかっちりとした印象に仕上がります。実際配置する位置が1px以下でずれている場合多少滲みますが、それを考慮しないにしても意識しない場合と比べると滲みは少なくなります。 400%で作成すると表示サイズは1/4になるので線幅24pxの場合表示サイズは6pxとなります。 400%にした理由 デザイン時に拡大縮小する際に偶数の方が扱いやすい 自分の環境(iMac 27インチ)で角丸の度数などの細部をみたいところまで拡大できる ポイント 最終的にSVGデータ(ベクター形式のデータ)で配置すればかなり綺麗に表示されます。 これからもっと解像度の高い端末が発売されることも見越した施策です。 (ただし、IE8以下、Android2.3以下は対応してないので、対象機種を確認の上実施することをお勧めします。) 4. 文字を知る 読みやすい文字を作るための知識 デザインする際にどんな風に装飾をするか迷うと思います。古来から伝わる文字には様々な 意味や特徴 があり、フォントのどこがどのように特徴を表現しているのかを分析しながら作成することで、読みやすい文字表現を作成することが出来ます。 参考になる文字ルール 《 セリフ (serif) 》 タイポグラフィにおいて文字のストロークの端にある小さな飾りを意味する。セリフを持つ書体をローマン体と呼ぶ。 《 サンセリフ 》 セリフのない書体の総称。 《 永字八法 》 漢字の「永」の字には、書に必要な技法8種が全て含まれているという事を表した言葉。 側(ソク、点)、勒(ロク、横画)、努(ド、縦画)、趯(テキ、はね)、策(サク、右上がりの横画)、掠(リャク、左はらい)、啄(タク、短い左はらい)、磔(タク、右はらい)の八法。 5. 印象に残るロゴを目指す イメージに合わせてモチーフをプラス 「キャリアとファミリーが繋がっている感じ(※課題1)の アイキャッチ が欲しい」というオーダーが入りました。 今回は関係者内で協議の結果「バランスが取れてハッピーになる」というイメージで「やじろべえ」のモチーフを起用することに。 物理的に不自然にならないよう左の丸が大きくなっています。 ポイント モチーフもできるだけ正円を使うなどし、文字部分とのバランスをとりましょう。 6. 配布用データを作成 いつでもどこでも綺麗に表示してもらうために ロゴは媒体に配ったり、どこかに掲出してもらう機会もあり 一人歩きしがち です。 そんな時、カラーなどを明記したドキュメントとガイドラインがあれば是か否かハッキリし、 扱う人も迷わずに済む でしょう。 ロゴが見えなくなったり読めなくなったりしそうなケースは洗い出し、禁則の欄に追加していきましょう。許容を決めておくことも大事です。 まとめ 今回はWebサイトのサービスロゴ(しかもスマートフォンファースト)ということでタイポグラフィーを採用しました。 Webの場合ファーストビューで何が得られるかが重要です。 ファーストビューに説明的な記載があることでユーザーがサービスにたどり着くまでに時間がかかってしまいます。 時間がかかってしまうと離脱につながります。 離脱させないために、説明がなくてもファーストビューで 「読める・分かる」 を軸に制作することが必要なのです。 特にロゴはファーストビューの大部分を占めますので、制作の際は下記の、目的を明確にし、それらが達成できるように心がけることが大切だと私は考えます。 メディア(媒体) 例えば雑誌には雑誌にしか表現できない印刷技術、TVには動きも表現に加わるなど、説明の余地などが媒体によって違います。 ターゲット デザイン要素を大きく左右します。 コンセプト 全体のデザインとマッチさせ、より強固な印象付けを図ります。 ※camilyにおいては、丸みを帯びた優しい印象のロゴタイプに加えUIは柔らかい緑で統一し安心感を表現しています。(※課題2) 以上、「スマートフォンでもキレイに見える!タイポグラフィーから作るロゴデザイン」でした。
こんにちは、メディアシステム開発部の山浦です。 年が明けたばかりだし、なにか新しいことを始めたいと思いまして、β版から正式版になったAWS IoTを取り上げてみることにしました。 AWS IoTとは 昨年10月のre:Inventで発表され、同年12月に正式リリースされたAWSサービスの1つです。 IoTに特化しており、デバイス同士の接続やAWS SNS、DynamoDBなどと連携することができます。 これまでIoT環境を構築するには、メッセージブローカーの構築やセキュリティ対策などいくつものハードルがありましたが、AWSによってマネージドされたサービスとして提供されたことにより、IoTがより身近なものになりました。 AWS IoTとデバイスは、MQTTまたはHTTPSプロトコルを介して通信を行います。 気になる料金ですが、東京リージョンの場合 100 万通のメッセージあたり 8 USD と設定されています。 IoTとは Internet of Thingsの略です。 世の中の様々なモノがインターネットに接続する技術のことをさし、 第4次産業革命のキーワードともなっている、とてもホットな分野です。 目標 下記のような流れを実装し、AWS IoTがどのようなサービスかを知りたいと思います。 Arduinoで光量をセンシング センシング結果をAWS IoTにパブリッシュ パブリッシュされた結果をAWS SNSでメール送信 Arduinoとは 初心者でも簡単に扱えるマイコンボードのことです。 さまざまなセンサと組み合わせることで、周囲の環境を感知することができます。 開発にはArduinoIDEという開発環境が用意されており、コーディングからプログラムの書き込みまでを一括して行うことができます。 AWS SNSの準備 それでは手始めにAWS SNSの設定から始めたいと思います。 こちらを最初に登録しておく必要があるため、AWS IoTを触りたい気持ちをグッとこらえて設定を行っていきます。 1. Topicの登録 Topicを作成します。AWS IoTでこのTopicを呼び出すことになります。 2. Subscriptionsの登録 Subscriptionsの設定をします。目標がメール通知なので、Protocolにemailを設定し、送り先のメールアドレスを登録します。 以上でAWS SNSの設定は完了です。 AWS IoTの準備 いよいよ本題のAWS IoTを設定してきます。 大きく分けて4つの項目を設定する必要があります。 Thingの登録・・・デバイス自体の登録します。 Ruleの定義・・・デバイスから受け取ったデータを処理するルールを定義します。 Certificateの作成・・・証明書、秘密鍵、公開鍵を作成します。 Policyの作成・・・AWS IoTの各種操作を許可するためのポリシーを作成します。 各設定を順番に行っていきます。CLIから行う方法もありますが、今回はすべての設定をコンソール画面から設定してみます。 1. Thingの設定 Nameを入力し、Createボタンで登録完了です。 Thingの設定はこれだけです。 2. Ruleの定義 まずはRuleの名前を決めます。 次に受け取ったデータを処理するルールを定義します。SQLになっているので直感で理解しやすいのが特徴です。 TopicFilterに設定した【topic/test】を設定した場合、同一のトピック名でパブリッシュされたデータを、次で定義するアクションに受け渡します。 パブリッシュされたデータをどのように処理するか定義します。 SNSとの連携を行いたい場合、【Send message as a push notification】を選択します。 (他にも、DynamoDB、Kinesis、Lambda、S3、SQSと様々なAWSサービスが選択可能です。) 続いて、一番最初に設定をしたAWS SNSの SNS Topic と Role Name を指定したら、Add Action をクリックしアクションを決定します。 最後にCreateボタンをクリックします。 3. Certificateの作成 証明書と秘密鍵と公開鍵を生成します。 既存のCSRから鍵を生成することもできますが、【1-Click certificate】を使用することが推奨されています。 鍵と証明書が生成されるとダウンロードすることができます。 鍵はこのタイミングでしかダウンロードできないので、忘れずにダウンロードしておく必要があります。 4. Policyの作成 デバイスに対して、AWS IoTの各種操作を許可するためのポリシーを作成します。 今回は全ての操作を許可するように設定します。 図の赤枠を入力したら、Createボタンをクリックします。 5. Certificateの有効化とThing、Policyのひも付け 最後にCertificateにThingとPolicyをひも付け、有効化を行います。 この行程を行うことで先ほどダウンロードした証明書と鍵が有効になります。 以上でAWS IoTの設定は全て完了です。 Arduinoの準備 Arduino側の設定は大きく分けて3つです。 回路の作成 Arduinoに組み込むプログラムの作成 Arduinoでセンシングしたデータを受け取りパブリッシュするプログラムの作成 1. 回路の作成 Arduino単体で光量をセンシングすることができないため、外部に回路を作ります。 実際の回路はこのようになりました。赤枠で囲んだものが照度センサです。 センサが受け取った値をアナログ0番ピンで取得できるようになっています。 2. Arduinoに組み込むプログラムの作成 センサの値を出力するプログラムを作成します。 言語はArduino言語という、C/C++をベースにした独自言語で使用します。 serial.ino int val = 0; void setup() { Serial.begin(9600); } void loop() { val = analogRead(0); Serial.println(val/4); delay(1000); } アナログINの0番ピンからデータを受け取り出力します。 ArduinoIDEでコンパイルが通ったら、Arduinoに書き込んでおきます。 3. Arduinoでセンシングしたデータを受け取りパブリッシュするプログラムの作成 AWS IoTにパブリッシュするプログラムです。 MQTTで通信できれば言語の指定はありませんが、今回はRubyで書いてみました。 (Arduinoは単体で通信が行えないため、パブリッシュはPCを介して行います。) 前準備として、serialportとmqttというgemが必要なのでインストールしておきます。 mqttはRubyからMQTTプロトコルで通信を行うためのgem、serialportはシリアル通信をするためのgemです。 $ gem install mqtt $ gem install serialport serial.rb require 'serialport' require 'mqtt' # Arduinoで設定したポート port = '/dev/cu.usbmodem1411' sp = SerialPort.new(port, 9600, 8, 1, SerialPort::NONE) client = MQTT::Client.connect(host: 'YourEndpoint', port: 8883, ssl: true, cert_file: 'certificate.pem.crt', key_file: 'private.pem.key', ca_file: 'rootCA.pem') loop do sensor_val = sp.gets puts "Illuminance = " + sensor_val if sensor_val.to_i Illuminanceの値は、明 40 ~ 250 暗 程度の値を取るので、やや暗いところで実行したことが分かります。 Illuminanceの値が【50】を切った時にAWS IoTにパブリッシュされるので、明示的に光源を照度センサに近づけてみましょう。 値が小さくなっているのが分かるかと思います。 実際にパブリッシュされた文字列がメールで送信されているでしょうか。 届いていました! センシングされた値を基にパブリッシュされ、AWS IoTからSNS経由でメールが送信されたことが確認できました。 まとめ AWS IoTを初めて使用してみましたが、設定から稼働までとても簡単にできました。他のAWSサービスとの連携が予想以上にスムーズに行えたことに驚きました。 今まで時間をとられていた環境構築の悩みをAWS IoTが解消してくれたので、あとはアイディア次第で面白いものを作っていけると思います。 今回はArduinoを使いましたが、もちろん他のIoTデバイスも使用可能なので、今後も色々と試していきたいと思います。 みなさまもステキなIoTライフを!
明けましておめでとうございます!auスマートパス開発部の新井です。 medibaで提供しているサービスではDynamoDBを利用しているサービスがあります。 Q: Amazon DynamoDB とは何ですか? Amazon DynamoDB は、完全マネージド型の NoSQL データベースサービスであり、高速で予測可能なパフォーマンスとシームレスな拡張性が特長です。 https://aws.amazon.com/jp/dynamodb/faqs/ DynamoDBは、スループット容量を変更することができ必要なときに必要なだけリソースを利用することが可能です。 DynamoDB での制限について ただ、スループット変更にあたっては制限があり増やす場合には日に何回でも可能ですが、減らす場合には日に4回という制限があります。 また、増やしたスループットが適用されるまでにはデータ量やデータ構造によって数分から数時間かかるという注意事項もあります。 Q: テーブルのプロビジョニングされたスループットレベルを変更するにはどのくらい時間がかかりますか? 通常、スループットを減らす場合は数秒から数分、増やす場合は数分から数時間かかります。 追加スループットが必要になった時点でスループットを増加したり増加のスケジュールを立てたりすることはお勧めできません。スループット容量のプロビジョニングは、必要なときに確実に容量を確保できるようかなり前から行っておくことをお勧めします。 https://aws.amazon.com/jp/dynamodb/faqs/ DynamoDB での制限一覧 https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Limits.html ユースケースに応じたデータストアの使い分け DynamoDBを利用する際には、ユースケースに応じて必要となるスループットが異なるケースがあるため他のデータストアと併用する案の検討が大事かと思います。 例 フロントエンド 訴求などによるスパイクアクセスにより特定の時間帯のみ高スループットが必要である バックエンド 日に一度だけ特定の時間帯に大量データを処理させるために高スループットが必要である 運用者が任意のタイミングで格納されたデータを集計/出力するために高スループットが必要である などなど 上記ケースの場合は、必要なときに都度スループットを変更することにより要求を満たすことは難しい状況となります。 また、バックエンドでのユースケースが実行されるタイミングでフロントエンドで利用しているテーブルのスループットを消費してしまうケースやバックエンドで利用するデータは、RDBMSで管理していたほうがデータを操作しやすいといった状況にもなります。 いつでも高スループット状態を確保できる状況であれば問題ありませんが、高スループット状態を確保しておくことにより費用面で課題が残ります。 そんなときには、DynamoDB Streams を利用することで別のデータストアへデータ同期することによりユースケース別に最適なデータストアの利用が可能となります。 データの流れイメージ DynamoDB と RDS の併用をした際にストリームデータを効率よく処理させるために着目したこと 今回紹介させて頂く事例は、DynamoDB から RDS へデータを同期する際に、DynamoDB Strems と lambda間で効率よく SQS へメッセージを格納する処理にてパフォーマンスをあげるために工夫/検証した内容を紹介します。 Amazon Simple Queue Service(SQS)は、高速で、信頼性が高く、スケーラビリティに優れ、十分に管理されたメッセージキューサービスです。SQS を利用すると、簡単かつコスト効率良く、クラウドアプリケーションのコンポーネントを切り離すことができます。 ※ 具体的な実装方法ではなく、パフォーマンス向上する上で着目したポイントの紹介となります。 ※ lambdaからRDSへ直接連携させるためにはセキュリティグループの開放などが必要となりセキュアではなくなるためSQSを経由しています。 ※ SQSからRDSへ効率よくデータを格納させる方法については触れていません。 着目ポイント1:DynamoDB Streams の Batch sizeについて DynamoDB Stermsを有効にする際には、「Batch size」という項目を指定可能です。 Batch size を 変更することによりパフォーマンスにどのような影響があるのでしょうか。 ※ Batch sizeで指定した値によって、ストリームデータが一度に処理される件数を指定することが可能となります。 着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について SendMessage と SendMessageBatchを使うことによりパフォーマンスにどのような影響があるのでしょうか。 ※ SendMessageは、一度に1件のメッセージを処理可能です。 ※ SendMessageBatchは、一度に10件までのメッセージを処理可能です。 着目ポイント3:lambda function の割当てメモリ量について lambda function の割当てメモリ量によりパフォーマンスにどのような影響があるのでしょうか。 ※ lambda function のメモリ割当て量を大きくすることで性能は向上するのですが、パフォーマンス検証をしている際に考慮すべきポイントがあったため着目ポイントとして取り上げています。 着目ポイントに焦点を当てたパフォーマンス結果について 以下の結果となりました。 DynamoDBへの書込は100TPS(トランザクション毎秒)にて書込処理を実施し、SQSへのメッセージ処理においても100TPSに近しい値がでることを目的として検証した結果となります。 ※ 利用したDynamoDBのテーブル構造、同期させる対象データ、lambda function等により異なる結果となるため、着目ポイントにおけるパフォーマンスがどのような相関関係となったかとして参照ください。 batch size message type 割当てメモリ量 SQSへの処理性能(TPS) 1 SendMessage 128MB 約6TPS 10 SendMessageBatch 128MB 約45TPS 20 SendMessageBatch 128MB 約50TPS 100 SendMessageBatch 128MB 約65TPS 10 SendMessageBatch 256MB 約77TPS 考えうる全ての組み合わせを試した結果ではありませんが着目ポイントを組み合わせることでパフォーマンスが向上することを確認できました。 まとめ 着目ポイント1:DynamoDB Streams の Batch sizeについて Batch size を上げることにより、一度に処理される件数が増えるためパフォーマンスが向上する。 上記結果には含まれていないのですが、極端にBatch sizeをあげることにより一度に取り扱うストリームデータの量が大きくなりすぎ着目ポイント3の割当てメモリ量を超えてしまい、ストリームデータが取り残されるという事象が発生しました。 ※ メモリ割当て量を増やすことで処理が実施されることは確認しました。 また、同様に極端にBatch sizeをあげることによりlambda functionの一度に取り扱うストリームデータ量が多くなりlambda functionのTimeout制限(デフォルト3秒)に引っかかりストリームデータが取り残されるという事象が発生しました。 ※ Timeout値を伸ばすことにより処理が実施される形となります。 ただし、lambda functionのTimeout制限は最大60秒となるため最大60秒以内に処理が完了するBatch sizeを指定する必要があります。 着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について SendMessageBatch にすることで、SQSへのメッセージ送信処理においてまとめてメッセージを送信することが可能となるためパフォーマンスが向上する。 注意点としては、batch sizeが 1の場合には、SendMessageBatchを利用したとしても一度に処理されるストリームデータは、1のためパフォーマンス効果はありません。 最低2以上に設定した場合のみ、SendMessageBatchを利用することでの性能向上が期待できます。 着目ポイント3:lambda function の割当てメモリ量について 割当てメモリ量を増やすことで、lambda自体の処理性能があがるため性能が向上する。 上記3つのポイントを処理をさせたい性能に合わせチューニングをすることでリアルタイムに近しい形でSQSへメッセージを格納することが可能かと思います。 最後に 今回紹介したパフォーマンスのチューニングポイントでは、SQSからRDSへもリアルタイムに近しい値でデータを同期させることは考慮できていません。 SQSからRDSへもリアルタイムに近しいデータを同期させるためには、SQSからのデータ取得間隔/Woker数、RDSへの書込性能などを考慮した上でチューニングを実施する必要がありますが、最終的にはDynamoDBにて確保する高スループット以上の書込性能をRDSで実現することは難しいと思われるためDynamoDBは、ユースケースに応じた利用することが大事だと思います。 DynamoDB Stremsについては、詳細な情報が公開されていない部分も多く、手探りで検証した結果となりますので 少しでも性能改善に役にたてれば幸いです。
新年明けましておめでとうございます。 本年もどうぞ宜しくお願い致します。 さて今回は制作部フロントエンジニアの苅部から、Charles(チャールズ)というアプリケーションをご紹介させていただきます。 このアプリケーションはHTTPプロキシを設定できるソフトで、通信の内容を覗いたり改変したりする事ができます。 日々のデバッグ作業に応用できますのでフロントエンジニアやディレクターの方、是非この機会に活用されてみてはいかがでしょうか。 Charlesを使ってできること デバッグで主に利用する機能は以下の4点です。 通信内容の詳細確認 通信内容の制御 帯域制御 スマートフォン実機でのデバッグ 設定方法 最初に、初期設定についてご説明します。 ※ ここではMacOS利用にて、スマートフォンがMacOSと同じネットワークに接続していることを前提とします。 MacOS CharlesのWEBサイトからダウンロードします。 https://www.charlesproxy.com/download/ Charlesをインストールします。 SSL通信も有効にするためSSLの証明書をインストールします。 SSL証明書の設定についてはオフィシャルのドキュメントを参考にしてください。 https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/ スマートフォン Macと同じネットワークに接続し、HTTPプロキシを設定します。 サーバ/プロキシホスト名にはMacのIPアドレス、ポートはCharlesで設定しているポート番号(デフォルトでは8888)を指定します。 iOSの場合 Androidでの設定 ※ SSL通信を有効にするためには、MacOS同様に端末へ証明書のインストールが必要となります。 ※ 端末からネットワークへ接続するとMacOS側にダイアログで"A connection attempt to Charles…“というメッセージが表示されるので、[Allow]を選択して、端末によるアクセスを許可してください。 ※ Android2系ではプロキシ設定のできる機種が限られているようです。 デバッグ方法 機能ベースではイメージしづらいため、実際の利用シーン別に操作方法をご説明します。 1. スマートフォン実機でデバッグを行いたい 例えばスマートフォン実機/商用環境にて何か問題が発生していて、すぐにデバッグが必要な場合があるとします。 PCであれば、ブラウザの開発者ツールなどを利用してある程度デバッグをすることができますが、実機でのiOS/Android/WEBVIEWではその方法が取れない場合があります。 こういったケースでCharlesを活用をすることができます。 ここでは[Map Local]機能を使い、mediba.jpへのアクセスでアラートウインドウを表示してみます。 1) ブラウザのDeveloper toolなどで任意のURLを拾います ここでは https://www.mediba.jp/includes/js/jquery/jquery.js としました。 2) デバッグ用の代替ファイルを用意します hoge.jsというファイル名にて、alertを実行するscriptを用意しました。 3) Map Localの設定をします [Tool] から [Map Local]を選択します。 [Enable Map Local]をONにして[Add]を押します。 [Map From]の[Host]の箇所に先ほどのフルパスを貼り付けます。 この後、別の項目にフォーカスするとフルパスが個々の項目に分解されます。 [Map To]では先ほど用意した代替のスクリプトファイルを選択します。 以上の手順によって、 * https://www.mediba.jp/includes/js/jquery/jquery.js のレスポンスを * [/Users/hoge.js]の内容で返す といった設定が完了しました。 リロードを行うと、Macのブラウザでもスマートフォン実機でもアラートウインドウでhello worldと表示される事が確認できると思います。 レスポンスとして返ってきているものであれば、img,css,jsなど全てのファイルを書き換えることができます。 これによって"商用環境/スマートフォン実機にて、外部ファイルの影響で問題が起きている"といったような特殊な状況でもすぐにデバッグが可能になります。 location.reloadやlocalstorage、DOM Selectorを利用すれば事象の発生確率の確認くらいはできると思います。 ※マッピングがうまくいかない場合 Charlesによってマッピングされているファイルは独自のレスポンスヘッダーが付与されています。 うまくいかない場合は、対象のファイルにX-Charles-Map-Localヘッダーが付いているか確認してみてください。 2. 非同期のデータ(スタブ)を用意したい 前述の事例と同様にMap Localの機能を利用して、読み込むファイルをJSONなどにしておけば、JSでの非同期処理におけるスタブデータとしても利用ができます。 これにより、例えばバックエンドの実装が終わっていない状態でも、APIの仕様を決めておけばフロントでもある程度先行して実装することができます。 3. 通信のログを確認したい メインのビューには常にログが流れていきます。 実機でもログが取れるため、実際のリクエスト数がどのくらいでそれぞれのレスポンスにどのくらいのコストが掛かっているかわかります。 個々の項目では、Overviewやリクエスト/レスポンスのRAWの表示が可能です。 4. 通信速度をコントロールしたい [Throttle Setting]機能にて帯域を制御できます。 例えば通信速度を極端に下げることによってページローダー的な、ロードの状況に応じて消えてしまう要素を確認することができます。 また実際にどの段階でページが描画されるか、ログと照らし合わせて確認できるためボトルネックの発見に繋がります。 例えば外部ファイルロードによるレンダリングブロックのポイント(クリティカルレンダリングパス)を確認することができると思います。 私自身も過去のプロジェクトで、この機能でデバッグを行いAndroidWEBVIEWのパフォーマンスを改善していた事があります。 帯域設定は[Enable Throttling]をONにして、任意のPreset/帯域数値を指定するだけです。 SIM契約の多様化によって十分に速度が出ないユーザーもいるため、低帯域でのパフォーマンス改善も大切かと思います。 5. ヘッダの内容を変更したい [Rewrite]機能を使うことで、リクエストヘッダやレスポンスヘッダの内容を変更できます。 そのためリクエストでのcookieを変更して認証まわりのデバッグを行ったり、 レスポンスでのCache-controlやExpiresを変更してブラウザのキャッシュ周りのデバッグも可能になります。 ここではリクエストヘッダーのUserAgent変更を例にとって、設定手順をご説明します。 1) Rewrite Settingを表示 [Enable Rewrite]にチェックを入れ、その下の[Add]を押します。 2) ルールセットの名前を設定 任意の名前を設定します。AndroidのUAに変更するため、ここでは"Android UA"としました。 3) Locationsの設定 今回はワイルドカードで設定しました。全てのURLで有効になります。 4) Rulesの設定 Rewriteに関する細かい指定を行います。 [Type]: Rewriteの振る舞いを選択します。 今回は既存のヘッダの変更となるため[Modify Header]を選択しますが、ヘッダー追加/削除,クエリパラメータの変更/追加/削除も可能です。 [Where]: Requestを選びます(リクエストヘッダー) [Match]: NameにUser-Agentを入力し、全ての値を対象とするため[Match whole value]のチェックを入れます。 [Replace]: NameにUser-Agentを入力し、Valueに任意のUA Stringで設定します。 ここではAndroidのUserAgentを入力しました。 この設定により、[iPhoneやPCでアクセスしていてもUserAgentは一律Android]となります。 この状態で試しにGoogle検索をしてみます。 UAがiOSの場合の検索結果 UAがAndroidの場合の検索結果 Androidに変更した状態では、検索結果のアプリ一覧にAndroidアプリが出てきているので Rewriteがうまくいっている事がわかります。 注意点 Charlesはシェアウェアですが、起動してから30分間は通常利用ができます。 30分経過するとアプリケーションが強制終了しますが、再起動してまた30分間使うことが可能です。 通信のログは止めない限りは残り続けるため、継続して使うとメモリが圧迫されてCharlesが落ちることがあります。 まとめ これまで紹介したようにCharlesは簡単なGUIに必要十分な機能が備わっており、誰でも気軽にデバッグができるソフトだと思います。 用意されている機能を応用することで通常では難しいデバッグも簡単にできます。 また、問題の切り分けにかかる時間が短縮されるため、業務効率の向上に繋がります。 ライセンスも$50以下ですので、機能から考えるとコストパフォーマンスはとても高いように感じます。 https://www.charlesproxy.com/buy/ Charlesは新しいソフトではありませんが(私自身も3年くらい使っていますが)、もしまだ使われていなければ一度触ってみることをお勧めします!
こんにちは!メディアシステム開発部の杉本です。 今回は、11月末にトライアルリリースをしたauスマートパスアプリ向け検索連動広告で利用しているElasticsearchのCluster機能の設定について紹介をさせてもらいます。 Cluster機能を利用することで、可用性の確保、レイテンシの低減が期待できます。 Elasticsearchでは標準でmulticastの設定となっており、Cluster機能を使うのはさほど難しいことではありません。 ただし、AWSはmulticastに対応していないため、AWS上のMulti-AZ構成でCluster機能を利用するのには少し工夫が必要です。 その前に注釈 10月にリリースされたAmazon ESのお話はないです。 もう少し早く発表されてたら検証し採用してたかもですが今回は見送りました。 kibanaも関係ないです。 最近はElasticsearchの情報検索してもkibana情報が多くて閉口しちゃう。 まずは、簡単に広告商品の紹介 auのAndroid端末にプリインストールされているスマートパスアプリ向けの検索連動型広告です。ナンノコッチャ ですね。 こうして、こうするとでてくる、これです。 ※ 画面イメージは2015年12月時点のキャプチャとなります。 ※ 掲出される広告は検索ワードや案件状況によりかわります。 ※ iPhoneユーザーは Appleストア からダウンロードしてみて下さい。 広告品質やユーザーと広告との接触状況、キーワードとの広告コンテンツの適合度などなど様々な情報を元に掲出する広告を決めているのですが、このプロダクトでは「キーワードとの広告コンテンツの適合度」の判定にElasticsearchを利用することにしました。 ElasticsearchでのClusterの設定 前置きが長かったですね。それでは本題。 流石に本番環境は披露できないので、似たような環境をブログ用に用意してみました。 環境 AWS EC2 t2.micro インスタンス * 4台 Amazon Linux Elasticsearch 1.7 plugin elasticsearch-cloud-aws 2.7.1 (今回のキモとなるプラグイン) elasticsearch-kopf (確認用 head等でも可) Clusterの設定手順 ロールの準備 インスタンスの準備 Elasticsearchのインストール elasticsearch.ymlの設定 確認 ロールの準備 { "Statement": [ { "Resource": [ "*" ], "Action": [ "ec2:DescribeInstances" ], "Effect": "Allow" } ], "Version": "2012-10-17" } まずは、AWS上で上記インラインポリシーを持ったロールを作成して下さい。 自分は”EsDescribeInstancesPolicy”という名前のpolicyにしました。 インスタンスの準備 最終的には4台構成としますが、 まずはt2.microインスタンス1台を用意しAMIを取ります。 インスタンス作成時に気をつけなければならないのは、先ほど作成したロールを割り当てるのを忘れないようにする事ぐらいです。それ以外については、ポチポチしながら作成していって下さい。 セキュリティグループを設定するのであれば9200番ポートを開けるのを忘れずに。 Elasticsearchのインストール インスタンスが用意できたので、SSHでログインし、Elasticsearchをインストールしていきます。 今回はサービス化していくためにrpmでインストールしています。 rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch vim /etc/yum.repos.d/elasticsearch.repo リポジトリの登録 [elasticsearch-1.7] name=Elasticsearch repository for 1.7.x packages baseurl=http://packages.elastic.co/elasticsearch/1.7/centos gpgcheck=1 gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch enabled=1 インストール yum install elasticsearch chkconfig --add elasticsearch clusterの利用とその確認に辺りプラグインを追加 Kopf(環境確認) /usr/share/elasticsearch/bin/plugin --install lmenezes/elasticsearch-kopf/master Elasticsearch-cloud-aws(自動clustering aws対応) /usr/share/elasticsearch/bin/plugin -install elasticsearch/elasticsearch-cloud-aws/2.7.1 elasticsearch.ymlの設定 設定ファイルはelasticsearch.ymlです。 通常であれば下記にあると思います。 vim /etc/elasticsearch/elasticsearch.yml clusterを利用するために必要な項目については下記です。 cluster.name: aws-cluster # node同士でクラスタ名は同じにする discovery: zen.ping.multicast.enabled: false type: ec2 cloud: aws: region: ap-northeast node.auto_attributes: true cluster: routing: allocation: awareness: attributes: aws_availability_zone 設定については以上です。 下記コマンドでElasticsearchを起動し service elasticsearch start http://xxxx.xxxx.xxxx.xxxx:9200/ へアクセスして、起動を確認してみてください。 ロールを設定することで、設定ファイルにsecret_keyを記載する必要もないのでよりセキュアな状態で構築できます。 1インスタンスでの設定を確認できたら、AMIを作成し、作成したAMIを元に4台のインスタンスを起動させて下さい。 確認 正常に設定が完了していれば後は確認するだけです。 http://xxxx.xxxx.xxxx.xxxx:9200/_plugin/kopf/ へアクセスをすると、下記のような画面が確認できるかと思います。 キャプチャから確認いただけるようにサンプルでは5つのshardに3つのreplicaをもたせる形でindexの作成を行いました。 設定については以上となります。 試しに、インスタンスを1台停止させてみてください。 下記のようにすぐにindexが再分配され、Cluster全体として問題なく動作していることが確認できるかと思います。 また、インスタンスを再起動させれば自動で対象のインスタンスを見つけ出し、indexが再分配がされたことを確認できるはずです。 このようにElasticsearchでは簡単にClusteringが行えるので、可用性の確保のためにも積極的に利用していきたいですね。
こんにちは。auスマートパス開発部の子安です。 最近すっかり寒くなりましたね。冬といえばコタツです。そしてコタツといえば双六。双六 -> サイコロ -> Redis。 ・・・はい、やっとたどり着きました。今回はRedisの話です。 全てのレコードを吐き出したい 今やKVSの代名詞と言えるほど使われているRedisですが、一つ困ったことがあります。 というのも、レコードを全てダンプするようなコマンドがないのです! みなさんどうしていますか? 素直なやり方 最初に思いつくのは、KEYSしてMGETかもしれません。 # export_by_keys.py r = redis.StrictRedis(REDIS_HOST) res_keys = r.keys() # KEYS if res_keys: res_mget = r.mget(res_keys) # MGET for key, val in zip(res_keys, res_mget): print(utf8(key), utf8(val)) >> 完全なコード これは手軽なのですが KEYS * は全てのキーを返しますので、レコードが多くなっていくとサーバ、クライアントともに問題が起きてきます。公式ドキュメントにも「普段使いは意図してないよ」とありました。 http://redis.io/commands/KEYS Don’t use KEYS in your regular application code. このドキュメントの続きにもある通り、こういった場合にはカーソルによって少しずつキーを取得していくSCANを使うのが作法です。 つまり次の手として考えられるのは、SCANとMGETですね。 # export_by_scan.py r = redis.StrictRedis(REDIS_HOST) next_cur = INITIAL_CUR while True: res_scan = r.scan(next_cur) # SCAN next_cur = res_scan[0] if res_scan[1]: res_mget = r.mget(res_scan[1]) # MGET for key, val in zip(res_scan[1], res_mget): print(utf8(key), utf8(val)) if next_cur == INITIAL_CUR: break >> 完全なコード このコードは問題なく動作します。が、SCANとMGETで2回ネットワーク越しにリクエストしているところが気になります。取得したキーをそのまま投げ直しているわけですから、ここは一括して処理できないものでしょうか。 Luaを使う そうかLuaを使えるじゃないか、と思って書いてみたのがこちら。 # export_by_lua.py r = redis.StrictRedis(REDIS_HOST) with open('scan_with_value.lua', 'r') as f: lua_script = f.read() scan_with_value = r.register_script(lua_script) # SCRIPT LOAD next_cur = INITIAL_CUR while True: res = scan_with_value([next_cur]) # EVALSHA next_cur = res[0] if res[1]: for key, val in res[1]: print(utf8(key), utf8(val)) if next_cur == INITIAL_CUR: break >> 完全なコード この中で読み込んでいるLuaスクリプトはこちら。 -- scan_with_value.lua local t_scan = redis.call('SCAN', KEYS[1]) if next(t_scan[2]) then local values = redis.call('MGET', unpack(t_scan[2])) return {t_scan[1], zip(t_scan[2], values)} else return {t_scan[1], {}} end >> 完全なコード やってることは同じくSCANしてMGETなのですが、Luaスクリプトはサーバサイドで動作しますので、クライアントからは一度のリクエストでキーと値のリストを取得できることになります。 比較してみる 1,000,000レコードを保持したRedisに対して実行してみます。 $ time python3 export_by_scan.py >/dev/null real 0m42.267s user 0m34.564s sys 0m2.384s $ time python3 export_by_lua.py >/dev/null real 0m46.726s user 0m35.100s sys 0m1.844s これは実はローカルに立てたRedisへ接続しているのでした。ローカルだと流石にあんまり変わらないですね。むしろ少し遅いぐらいです。 そこでリモートに同じく1,000,000レコードを保持したRedisを立てて、接続してみると・・・ $ time python3 export_by_scan.py redis-remote-host >/dev/null real 1m38.121s user 0m35.844s sys 0m2.780s $ time python3 export_by_lua.py redis-remote-host >/dev/null real 1m14.163s user 0m38.488s sys 0m1.864s 3/4程度の時間で処理を完了しました。ネットワーク次第とはいえ、充分有意な差が出たと思っています。 (おまけ)大量レコードの登録 吐き出すのではなく逆に投入する — 大量のレコードを登録する手順については、公式ドキュメントにガイドがあります。 http://redis.io/topics/mass-insert the preferred way to mass import data into Redis is to generate a text file containing the Redis protocol, in raw format, in order to call the commands needed to insert the required data. 要はプロトコルを流し込む仕組みがあるということですね。公式はRubyで書いてあったのですが、ついでなのでPythonで書きなおしてみました。 # to_redis_protocol.py def to_redis_protocol(*cmd): protocol = '' protocol += '*{0}\r\n'.format(len(cmd)) for arg in cmd: protocol += '${0}\r\n'.format(len(bytes(arg, 'utf-8'))) protocol += arg + '\r\n' return protocol >> 完全なコード まとめ 正直な話、全レコードをダンプする要件があるとしたら(そしてレコードが大量になるとしたら)、それは要件を考え直した方が良いかもしれません。なぜならその処理は必ずシリアルになり、スケールしないからです。SETイベントを通知して何らかの処理を入れるとか、Lua拡張で更新処理とともに何らかの処理を入れるなどの代案を検討すると良いでしょう。 それとLua拡張は面白いですよね。工夫次第でいろんなことができるので遊んでみてください。Luaの言語仕様もそれほど大きなものではありませんし、気軽に書けると思います。 今回使ったもの Redis 3.0.5 Lua 5.1.4 Python 3.4.3 / redis-py 2.10.5
こんにちは! mediba 制作部 メディアクリエイティブグループでデザイナーをしている高柳です。 最近、Webサイトやスマートフォンアプリの開発・改善を行うときのUIデザインツールとして、Photoshopやillustratorより Sketch を使うことが多くなってきているようです。 参考データ 2015 Subtraction.com Design Tools Survey 私も使い始めているのですが、便利機能が多くて使い易いのが魅力です。 今回は、そんなSketchについてご紹介したいと思います。 その1:デバイスに合わせたアートボード iPhone6を選択すると上の図の通り、アートボードが作成されます。 iPadやAndroid用アイコンを選択した場合は、それぞれ選択したデバイスに合ったサイズのアートボードが作成されます。 また、種類が多いためかAndroid画面サイズのアートボードはないですが、自由にサイズ登録して使うことができます。 その2:図形やテキストのスタイルを登録、シンボル化できる 図形やテキストのスタイルを登録して使い回せる テキストであれば、フォントの種類・色・サイズなどのスタイルを名前を付けて登録、管理できます。もちろん図形に関しても同様です。 登録してあるスタイルを図形やテキストに適用することで、一括でスタイルを変更することができてとても便利です。 よく使うアイコンやテキストたちをシンボル化 上記のスタイル登録と似た機能ではありますが、こちらはアイコンとテキストをまとめて管理できます。 例として、ページ下部のタブバーをシンボル化しました。 違うページを何枚もデザインしていると同じタブバーを繰り返し使うことになります。シンボル化することにより、デザインの変更が各ページに一括で反映されます。 その3:デバイスごとのパーツ書き出し機能 iOS解像度(dpi)ごとのパーツ書き出しが便利 スマートフォンアプリの場合、解像度(dpi)ごとにデザインパーツを書き出さなければならず、これがとても面倒です。 ですが、この機能を使うと2倍・3倍などの倍率を指定するだけで一瞬で書き出すことができます。 プラグインを使うとAndroidも書き出しも可能 Sketchのデフォルト機能にはAndroid用がないため、プラグインをインストールすると便利です。 iOSよりもAndroidの方が解像度の種類が多いので、ぜひプラグインを入れて使ってみてください。 その4:ダミーデータを入れるプラグイン 画像やテキストのダミーデータを入れるのは意外に面倒だったりします。 でも本物っぽいデータを入れてみないとイメージが湧かない・・・という時におすすめです! このプラグインを使えば、サムネイル用のシェイプや文章用のテキストエリアを作成すると、ダミーデータを挿入してくれます。英語だけでなく、日本語も対応しています。 その5:iPhoneに専用アプリを入れると作成中の画面を実機で確認できる Webサイトやスマートフォンアプリのデザインをしていると、実機ですぐに確認したいと思うはずです。 ですが、通常はデザインしたデータを書き出して、プロトタイピングツールなどにアップして・・・など少し手順が面倒だったりします。 しかし、このアプリは作成中のデータをリアルタイムに同期してくれるため、専用アプリをインストールしたiPhoneを用いることですぐに確認ができます。 その6:Prottと連携するプラグイン その5で紹介した専用アプリは有料です。 そこで、この専用アプリの代わりをしてくれる Prott との連携がとても便利です。 ほぼ便利機能その5と同じくリアルタイムに同期してくれる機能があり、そのままProttを使ってプロトタイプを作ることもできます。 Sketchを使ってみた感想 Sketchには下記のメリットがあります。 Adobe製品に比べるとお手頃価格 ¥11,800(2015年11月17日現在:App Storeでの金額) プラグインが充実している スマートフォンアプリ用パーツの書き出しが圧倒的にラク psdデータに比べるとデータが軽く、動作がスムーズ CSS で出来る装飾しかSketchで作れないという機能制限があるが、逆に実装できないデザインにならずに済む Adobe製品も最近はSketchのような機能を追加してきていますし、Adobe製品にしかできないこともまだまだあります。 ただ、使ってみた結果、 SketchはUIデザインに特化したツール だと感じました。 特にスマートフォンアプリのUIデザインをするならば、Sketchが便利ですので、みなさんもぜひお試しください!