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

TECH PLAY

株式会社mediba

株式会社mediba の技術ブログ

全218件

こんにちは。mediba制作部の大村です。 現場でAdobe Creative Cloudを使っているデザイナーさんに朗報です! 既に現場でも使い始めたのではないかと思いますが Adobe Experience Design (以下XD)を使うと普段の作業がサクサクスムーズなんです。2016年6月にリリースされたバージョン4で、メニューが日本語対応となりとても使いやすくなりました。 ちょっと触ってみましたので、レビューします。 参考記事 : Adobe XD Preview 4 リリース!日本語UI、オブジェクト間の距離計測、ぼかし機能など 1. Adobeユーザーなら学習コストほとんど無し 少しづつだけど確実に時短できる PhotoshopやIllustratorを使ってUIデザインしている方には、 作業時間の短縮 が見込めますので、是非使用して欲しいツールです。 ソフト自体のUIは洗練されましたが、アートボードやオブジェクトの操作方法など基本的な使い方がAdobe製品は統一されている為、Adobeユーザーであれば使い方を調べたりせずとも直感的に使えます。 また、これからWebデザイナーを目指す方にも、操作が簡単なのでオススメです。 グラフィック用のツールと違いUIデザイン用に作られたツールなので、ページもサクサク増やせ、移動や複製も小数点以下が出にくく、更にシンプルなのでデータ自体とても軽いので、細かいことは気にぜず邁進できます。 移動や変形、オブジェクトを作成する際も小さな文字で数字が表示され自分の動作が可視化されるので、作りながら考えることができ後で細かい確認が削減されます。 注意 :バナーやイメージ画像のような凝ったものは作れないので、完成するためにはPhotoshopやIllustratorも併用します。 Adobeのショートカットがそのまま使える 使えるショートカットの一例 機能 Mac / Windows グループ ⌘+G / Ctrl+G グループ解除 Shift+⌘+G / Shift+Ctrl+G コピー ⌘+C / Ctrl+C カット ⌘+X / Ctrl+X ペースト ⌘+V / Ctrl+V 全面に移動 ⌘+[ / Ctrl+[ 最全面に移動 Shift+⌘+[ / Shift+Ctrl+[ 最背面に移動 Shift+⌘+] / Shift+Ctrl+] カーソル1px移動 方位キー / 方位キー カーソル10px移動 Shift+方位キー / Shift+方位キー 2. データが軽い・共有もワンプッシュ Web上にデータを上げてすぐに共有 共有してすぐに端末で操作確認ができるのも魅力です。 共有は InVision や Prott などのプロトタイプツールにもある機能ですが、デザインデータを別で持っている場合もあり、デザインしてそのデザインをプロトタイプツールに反映し、更にプロトタイプを変更して共有しなければなりません。 XDでは、1度オンラインで共有したのち、 「再共有」→「リンクを更新」 するだけで変更が反映されます。 この早さ、手順の少なさは特記すべき魅力です。 3. デザインとプロトタイプの2in1 同時にできることでデザインを効率的に進められる 他のプロトタイプツールは、プロトタイプとデザインを別のツールで行う必要があります。 初回に組んでしまえば修正段階での煩わしさはあまりないのですが、アプリケーションを横断した作業が面倒、且つタイムラグがあったりもします。 XDなら 作りながらプロトタイプ でき、ページを少しづつ増やすことも簡単です。 増やしたページを繋げながらデザインが進められるので、ページを繋いだプロトタイプを頭のなかで考えながら作業する必要がありません。 労力が格段に少なくどんどんデザインが作れます! 4. こだわり過ぎる方にオススメ 細かく変更できないのが正解 画像はアートボートを移動したときの例ですが、一定の間隔で置いた場合その数値の場所にスナップするので並び替えもグイグイできます。 個人的にはドラックアンドドロップして出る端数が苦手でデザイン作成時にドラックはぜずXYの数値変更かカーソルキーでしか移動しないのですが、 スナップが的確 且つ 思ったところにガイドが出る ので、細かいことを気にせずとても気持ちよく移動・変更ができます。 細かく変更や調整ができないので、余計な細かい作業に捉われる事無くUIデザインを完成させることができます。 「1pxずれちゃった!コピペしたこの素材もこれの相対で動かしたパーツ達も全部ずれてる!整えなきゃ!(また2時間かかるわ…)」なんてことが激減します。 自動の機能が時短の鍵 XDに出会う前はIllustratorでUIデザインをしていました。 感覚的にはIllustratorに近い操作感なのでIllustratorや InDesign などのAdobeレイアウトツールを使っていた方からすると自動化された便利な機能が沢山あります。 一つは上の画像のように、右上の整列の下 「グリッドの繰り返し」 。 繰り返したボックスの中に画像を入れると、アルファベット/数字/五十音順など決まった順番、且つボックスのサイズに合わせてトリミングされ、一気に表示される機能があります。 繰り返したグリッドの変更も1箇所反映すれば全てに自動で反映されラクチンです。 また、UIデザインパーツ(UI KITS:Apple iOS、Google Materialデザイン、Microsoft Windows)が搭載されているので今まで探したり作ったりしていた手間が省けます。あとは日本語のキーボードのキットが搭載されれば最強かも?! 5. まとめ 作業時間を短縮してモックをたくさん作る UIデザインはページの前後関係や実際ページを見たときの UXを鑑みることが大切 なので プロトタイピングが必要不可欠 だと考えます。 作成する上で、遷移先がWebなのかアプリ起動なのかでも遷移元のUIは違ったものが適しているかもしれないという想定がされます。 想定だけでなく、 実際作って触ってみて ユーザーの視点に立ち考えることで全く違った考えも生まれてくるので、たくさん試して色々検討する時間の方が大事だと思います。 それを実現する為には「時間が欲しい!」と思っていましたがXDならあまり時間をかけなくても実際触れるものが作れると思いました。 今は自分の時短優先でXDを使用していますが、GithubやSlackなどチーム連携も考えると、XDよりも適したツールがあるかもしれません。 作業時間のさらなる短縮を目指し、最短でリリースが可能なUIデザインツールを模索していきたいと思っています。 他にも便利そうなプロトタイピングツール一覧 pixate CRAFT Silver Flows Affinity Designer Sketch InVision Prott
こんにちは、広告システム開発部の八代です。 今年の4月に広告システム開発部に異動し、広告の知識やシステムに携わることが多くなってきたため、そこで得た知識と最近何かと話題になって来ているVRコンテンツを融合させたバーチャルインターネット広告(ゲーム広告)を簡単に作ってみました。 今回やりたいこと 現実世界の看板と同様に仮想世界の看板に広告を表示させるような簡易的なものを作ってみる。 環境 本記事では以下のソフトウェア・プラグインなどを用いています。 Ruby Ruby on Rails 4.2 Unity 5.3 [Assets] Japanese Naniwa City (ZENRIN) [Assets] Character (Standard Assets) AdEngineの作成 AdEngineと大げさな言い方をしていますが、リクエストを受けたら表示する枠を判断して広告を返す想定のものを作 りました。 Railsが入っている想定で話を進めて行きます。 今回サーバー側で行うのは、表示する枠を判断して広告を返すものです。 まずは枠と広告を紐付ける為の処理をgenerateを使って簡単に作っていきます。      $ rails generate scaffold AdFrame title:string filename:string    $ rake db:migrate     それっぽい物が作れました。 次にリクエストを受けるためのコントローラを作成します。        $ rails generate controller home index     ルーティングの設定   .config/routes.rb . .root :to => 'home#index'   idが来たら該当ファイルにリダイレクトさせます。 home_controller.rb def index  if params[:fid].present?    file = AdFrame.find(params[:fid])    redirect_to '/images/' << file.filename  end end バリデーションチェックなどはしておらず必要最低限の実装をしていますが、ひとまずサーバー側の処理としては以上です。 UnityProjectの作成 新規3Dプロジェクトを作成し、 StandardAssetsのCharacter と JapaneseNaniwaCity を入れておきます。 まずは前準備としてマップの成形と広告を見るためのキャラクターを用意します。 キャラクターのプレハブとマップをヒエラルキーに追加。 キャラクターを地面に立たせてあげたいので Osaka_Ground と Osaka_Prop のインスペクタ Generate Colliders を有効にしておきます。 キャラクターの位置を調整し、マップ上に立たせてあげます。 次に広告を表示するためのスクリプトを作成します。 using UnityEngine; using System.Collections; public class AdRequest : MonoBehaviour { public string url = "http://local.unity-ad-engine.mediba.jp/?fid=1"; IEnumerator Start() { using (WWW www = new WWW (url)) { yield return www; if(!string.IsNullOrEmpty( www.error )){ yield break; } Renderer renderer = GetComponent<Renderer>(); renderer.material.mainTexture = www.texture ; } } void Update () { } } また、広告を表示するための面を用意します。 Create -> 3D Object -> Plane Planeのコンポーネントに先ほど作ったスクリプトを適応させてあげ、位置を調整して実行してみると・・・ 看板広告を表示することが出来ました! また、街中にあるビジョン広告のように動画を流すために同様にスクリプトを作ってあげ、動画表示用のマテリアルに適応させてコンポーネントに追加すれば、動画も表示することが出来ました! まとめ Unityだと簡単に広告を表示させられる仕組みが整っているので、 広告配信するためのサーバさえ立ててしまえばスクリプト1つを入れるだけで出し対面に広告を表示することができることがわかりました。 今後VRコンテンツが出てきた際にそのコンテンツにプラスαの収益元として広告が注目されるのかもしれないですね。
こんにちは。メディアシステム開発部の土方です。 最近社内でも色々なプロジェクトに関わらせていただくようになったのですが、その中でも長く携わっているプロジェクト、「 au Webポータル (スマートフォン版)」についてご紹介させていただきます。 上記サービスでは開発プロセスとしてスクラムを採用してもうすぐで丸3年になります。先日100Sprintを超えたということもあり、ちょっと振り返ってみようと思います。 「スクラム」「アジャイル」自体の情報は本もたくさん出ていますし、 検索すれば簡単に触れることが出来ると思うので、 そのあたりの用語や概念はそちらに譲らせていただき、 ここでは現場での自分の体験や思い出を中心にお伝えしたいと思います。 はじめに まず、現時点での開発プロセスの選択思想は大筋以下となります。 要件の内容や優先順位が1週間/2週間くらいの周期で変更され続ける開発現場で、 より効率的にアウトプットを出したい。 継続的にアウトプットを出し続けたい。 そのために、 「アジャイル宣言の背後にある原則」 「アジャイルソフトウェア開発宣言」 を大事にして、 「アジャイル開発ソフトウェア開発手法」の一つとして 「スクラム」のプラクティスを採用しています。 という整理です。     時系列的にはなんかイイ開発手法らしいぜ→「スクラム」のプラクティスを導入。それから開発宣言や原則を学んで理解していった、という流れなのですが、、チームが自己組織化されていって、チーム内部で定期的に細かな改善が為されるようになっていったのは、開発宣言/原則 に触れるようになってからじゃないかなと感じています。 なので、いま実践しているけどなんか上手く行かないなぁ、 と思ったら、プラクティスやTODOを確認するのもいいんですが、 まずは何のために何を大事にしてどうやってるんだっけ?ってアジャイルソフトウェア開発宣言、アジャイル宣言の背後にある原則から振り返ってみることをお勧めします。ただ妄信的にプラクティスをやるだけじゃなくてそのプラクティスの意味を考えなおす機会にしたらいいんじゃないでしょうか。先週も朝会で使っているカンバンが、形骸化してうまく対話の元になっていない気がしたので改善しないとね、と話をしてみました。 100Sprint体験記 導入期(2013/08頃): この時期に乗り越えた壁:導入 乗り越えるための鍵になったこと: 上役からの支援、これまで達成してきた成果などから、関係者に信頼してもらって導入に協力してもらった、という感じです。やっぱり新しいこと始める時に銀の弾丸って無いですよね。参考にならなくてゴメンナサイ。 思い出 開発チームとして「スクラム」を導入したい!と提案 「要員が固定されている(社内特有の事情による)のに、納期と要件ありきで激務続きだと長期的にはチームが保たないよ!要員を固定しているんだから、作業量が増減したらリリース日が一緒に動くっていうことだよ!」というメッセージとともに、「スクラム」は無駄な開発を抑止して、効率的により多くのユーザバリューを届けるためのよい手法で、要件変更が頻繁に起きる現場に適切だ、と説明した記憶があります。 もちろん、「約束したリリース日を後から調整するプロセスなんておかしくないですか?」などの質問含め議論になりました。いままでのウォータフォールのプロセスで考えたらそれは真っ当な疑問。 でもプロジェクトは現実に色々変更が起きるの常だし、メリットデメリットを整理した上で、納得してくれてとりあえず導入してもらうことにしました。リリース日は一度決めたら変更が困難であるということなのであれば、 最初にそれよりも短い期間でバーンダウンしきれるように計画/提案することにしました。 当時の印象的な調整 「リリース日はもっと細かく出来ないの?文言変更とかどう考えても3営業日もあればできるでしょう?」 確かにそれだけみればそうですよね。でも当初はできるだけ断ってました。 Sprintを1week単位に設定して、細かく要件の状況をヒアリングできるようにチームのリズムを設計はしたものの、チームのリズムや、開発者達が継続的に安定してアウトプットを出すことを大事にしようとしたからです。 どこまでは割り込んでいいのかの基準が曖昧になっていって、際限なくイレギュラーな割込みが入り込むことでリズムが崩れることを嫌ったというのが正直なところです。 でもいま振り返ると、スクラムのプラクティスに偏重していてアジャイルソフトウェア宣言に従ってなかったんじゃないか、とも思ったりします。この辺りの時期はお客さまや社内のプロダクトオーナー役によく我慢してもらったと思います。 講師を招いてアジャイル研修会 開発担当だけではなく、ディレクション担当も含めてアジャイル研修会を受講しました。何となく社内でも「アジャイル」という用語が認知されるようになった頃かなと思います。 学習期(2013/10〜2014/03): この時期に乗り越えた壁:教科書からの脱却 乗り越えるための鍵になったこと: 私が頭でっかちタイプなので、本を読んではそのプラクティスを極力厳密に適用しようとしていました。スクラムを実施する際の細いルール(例えばユーザストーリーの書きっぷり)に拘って、現場が疲弊しがちだったんですが、講習や勉強会など様々な実践例などを聞いて、現場現場でやり方は工夫していけばいい、教科書通りにしなくてもうまくいくまで改善すればいい、とわかってきて少し肩の力を抜けるようになった気がします。拘るべきはプラクティスじゃなくて、ユーザに継続的にvalueを届けるにはどうしたらよいのかいつでも考えるコト、困ったり良くないことがあったら改善していけばいいんだというコト、に気が付いてきました。 思い出 とにかく試行錯誤 「SCRUM BOOT CAMP THE BOOK」や「アジャイルサムライ」を読みながら、ああでもないこうでもないと実践と改善を繰り返していたように思います。社内で同じようにスクラムを採用しているチームのメンバと情報交換などしながら、デイリースタンドアップについて議論したり、計画/振り返りのMTGが長くなりがちなのでバックログの精査のタイミングを調整したり・・・ととにかく手探りですが意識的にトライアンドエラーをしていました。 安定期(2014/08〜2016/03): この時期に乗り越えた壁:お客さまに「スクラム」を認知してもらう 乗り越えるための鍵になったこと: プロダクトオーナー役兼お客さまとの調整役から、粘り強く「スクラム」によるメリットを伝えて続けて貰った結果、一定の理解と協力を頂けるようになりました。 具体的には、 プロダクトバックログの優先順位の整理実施の協力 ベロシティを基に各要件のリリース時期の見通しが分かることの理解 割込みでの要件差し込みはなんらかのタスクとのトレードになること など。 納期ギリギリまで頑張りきったけどやっぱり無理です、ということが減り、 どうして計画を変更しないといけないのか、が伝わりやすくなったのが大きいように思います。これにより、安定/安心して開発に集中でき、チーム内での信頼関係の構築、変化への対応力などが改善されたように感じていました。 思い出 チームに自律性が育ってきた 要員を固定する、とはいったものの、ベロシティを中長期的に増大させていくため、メンバが徐々に増大していき、徐々に情報共有のコストが高まり始めた時期でもありました。メンバの入れ替わりもありましたが、全体の仕組みが定着してきているので、新規参画メンバも比較的すぐに慣れることが出来るようになってきた時期だったように思います。 チームの要員が増大することで出てくる問題も、以下の様なチーム内での改善で対処するようになりました。 デイリースタンドアップで、今日のTODOと合わせて帰る時間を宣言する→忙しさが何となく伝わる→助け合える Sprintの途中で全員の進行状況を明示的に確認する係を立てて、輪番で廻してみる 開発の時間をよりまとめて確保するためにSprintの単位を1週間から2週間に変更してみる 変動期(2016/04〜): これから乗り越えないといけない壁: お客さまの担当変わっちゃったし、その流れでデカイ要件がガッツリ納期ありきで入ってきた!(これまでの現場のアウトプットのペースは評価されていないのかも!?という不安とともに) 乗り越えるために頑張ってること: なぜその納期でこの要件をやり切らないといけないのかについて、開発メンバへの説明 要員を急激に増員してもアウトプットは急激には上がらないことをお客さまに説明 タスクを分割して作業量の見える化 → 達成できるアウトプット量を見える化することで、優先順位下位の要件の整理 デカイ要件が変更なし、で進められるのであれば、細かく要件を変更するための時間は削減して良いハズ → タイムボックスのバランスを変更して一時的にでもアウトプットを上げる などなど・・・。 おわりに アジャイルは死んだ? アジャイルは死んだ、なんて記事をよく見かけるようになりました。「アジャイル宣言の背後にある原則」は全面的に正しいかと言われるとちょっと悩ましいところもあるものの、いまのところは出会えてよかった考え方だなと感じています。開発のプロセスやプラクティスは解決したい課題や状況に応じて選ぶべきものとは理解しているつもりですが、スクラムは細かく情報共有しながら進んでいくので、楽しいなぁと感じることが多く、もうしばらくは贔屓にしたい気持ちです。会議の時間がちょっと多すぎる嫌いもあるので、そのあたりはプロジェクトごとに調整しながら、ですね。 また、アジャイル/スクラムを通して、小さく速くPDCAを廻していくことが如何に大事なのかを考えさせられることが多いです。100Sprintを振り返るにあたって、導入、学習、安定、変動と分けてみたものの、考えたらいつもその瞬間は変動期だったなぁと思います。イライラしながらストレスフルにお仕事している時間は勿体無いから、上手くいかなかったら継続して改善していくしかないですよね! 求む!永続改善スタイルエンジニア! ということで、medibaでは、共に問題を見据えて改善に取り組み続けることが出来るエンジニアを求めています。少しでも興味を持って頂けましたら 募集ページ より詳細をご確認頂けるとなによりです。
こんにちは、制作部の今野です。 数年前からGoogle検索や翻訳などに、マイクのアイコンを見かけるようになり、好奇心でマイクをクリックすると、マイクが反応したり、ブラウザが喋り出したりしてビックリしました。 最近、どんな技術で実装しているのかな?と、色々調べていくうちに、「Web Speech API」というのを知り、これをうまく使えば、Botも楽しくなるんじゃ?と思い、調査しました。 Web Speech APIとは? ブラウザで音声の入出力ができる2つの機能があります。 テキスト読み上げ(Speech Synthesis API) テキストの内容をブラウザが喋る 音声認識(Speech Recognition API) 自分が喋った内容を、テキスト化などしてくれる(マイクが必要) 今回は、Speech Recognition APIについては以降出てこないので、実際に体験したい方は、Googleの デモ をご覧ください。 ブラウザに喋らせてみる 以下コードを、ChromeのConsoleか、HTMLのスクリプトに貼り付けてみてください。(喋るので音量注意!) speechSynthesis.speak( new SpeechSynthesisUtterance('Nice to meet you') ); おお、喋った! ん?でも、何か発音悪いですね。 そうなんです、言語設定をしてあげないと、正しい発音してくれません。Chrome日本語版では、デフォルト日本語設定にしているようです。 では、英語の設定にしてみましょう。 var synthes = new SpeechSynthesisUtterance(); synthes.lang = 'en-US'; synthes.text = 'Nice to meet you'; speechSynthesis.speak(synthes); ちゃんとした英語の発音になりましたね。 synthes.lang に指定した言語を入れると、その言語の発音になります。 synthes.text は、喋らせたい内容を入れます。 次に使い回ししやすいように、関数化してみました。 (オプションで音量・速度・音程なども調整できます) function say(msg, lang){ var synthes = new SpeechSynthesisUtterance(); // 発話機能をインスタンス化 // オプション設定 synthes.volume = 1; // 音量 min 0 ~ max 1 synthes.rate = 1; // 速度 min 0 ~ max 10 synthes.pitch = 1; // 音程 min 0 ~ max 2 synthes.text = msg; // 喋る内容 synthes.lang = lang || 'ja-JP'; // デフォルト:日本語、他 en-US etc.. speechSynthesis.speak(synthes); // 発話実行 synthes.onstart = function(event){ console.log('喋り始めました'); } // 開始時の処理 synthes.onend = function(event){ console.log('喋り終わりました'); } // 終了時の処理 } say('How are you?', 'en-US'); Botを作る ブラウザに喋らせるところまでいきましたが、毎回コードを修正して喋ってもらうのは、面倒ですし対話している感がありません。 そこで、対話ができるBotを作り、喋らせてみましょう。 Botを作る方法は色んな選択肢がありますが、今回は docomo Developer support の 雑談対話API を使ってみます。 docomo Developer support APIについて 他にも画像認識など様々なAPIを提供しており、Web・ネイティブアプリ開発時に活用できます。 また、今回は実施しておりませんが、日本語ではブラウザの音声は女性の1種類しか利用できないのですが、docomoの音声合成APIを使用すると「元気なお姉さん」お婆さん」「メイド」「癒やし系お兄さん」などの音声にもでき、人の声に限りなく近い喋り方になるようです。ブラウザだと棒読みに聞こえるので今度使ってみたいです。 まず、以下のようなJSONを用意します。 { 'utt' : 'こんにちは', // 送信するメッセージ 't' : 20 // キャラクタ設定。20は関西弁の女子高生 } 続いて上記JSONをAPIに投げてみます。(サンプルコードはFetchを使用していますが、普通にXMLHttpRequestでもOKです) fetch( 'https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=' + '発行されたkeyを入れる', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(apiJson) }).then(function(response){ return response.json(); }).then(function(json){ console.log(json.yomi); }); すると、json.yomiというオブジェクトに返信内容が格納され返ってきますので、先ほど作成した関数の say() で返信内容を喋らせます。 例 送信:こんにちは 返信:よっ、こんー、やあ ※毎回同じ回答がくるわけじゃないです。(女子高生なので喋り方がゆるいですw) 画面を作る Botも毎回コードを修正するのは煩わしいので、テキストボックスからBotとチャットできるように作ってみました。(入力した内容を上記APIに渡しているだけなのでコードは割愛します) ※メッセージは、上から最新順です おお、チャットで会話してる感が出てきました。 でも、見た目が寂しいですね。 ちょっと装飾してみます。 API仕様で「関西弁の女子高生」という設定なので、カワイイ女子高生の写真素材を、 ぱくたそ からいただいてきました。 どうでしょうか? 一気に、Botに親近感が湧くようになりましたね。 (作りながら思ったのですが、マイクロソフト 女子高生AIの りんな に似てきた。。) 静止画だと分かりづらいので、雰囲気が伝わるようにアニメGIF動画も載せておきます(途中、内容がアレですが。。) なお、画像からでは分かりませんが、きちんとテキストの内容にあわせてブラウザが喋ってくれてます。 Speech Synthesis API対応ブラウザ 残念ながら全てのブラウザが対応しているわけじゃなく、主にChromeとSafariが対応しています。 Edgeの最新版から対応し始めたようですので、使用するサービスが増えてきそうですね。 まとめ 今回はBotとの会話で使用しましたが、他にはチュートリアルのナビゲーターとして喋ってもらったり、ブラウザに歌わせてBGM(※)としてするというやり方もできるかと思います。 ※他の方が作られたものですが、 歌わせているサンプル です ただ、日本語の喋り方が棒読みなので、今回の女子高生写真と凄く違和感があります。 もっと人間に近い喋り方をしてくれることに今後に期待です。 また、今回、テキスト入力での会話でしたが、前述の「Speech Recognition API」の音声認識を使えば、実際の声と声でしBotと会話するということもできます。 おまけ 今回、docomoの雑談対話APIを利用しましたが、プログラミング無しでもAIが搭載されたBotを作成できる Repl-AI というサービスもβ版のリリースがされたようです。 プログラミング知識無い方でも利用できるようなので、今後様々なサービスでもBotやAIの技術が取り入れられてくると思います。 今回動作確認した環境 PC版 Google Chrome Ver. 50.0.2661.102 日本語版
はじめまして。インフラストラクチャー部の山下です。 各種サービスのAWSインフラを担当する傍ら、社内ではRubyやRailsなどを書いてたりしています。 私が参加しているプロジェクトで、AWSの各リソースが正しく構成されているかを確認したいという話が出たため、 awspec を導入してみました。 awspecとは? Serverspecのように、AWSの各リソースをテスト出来ます。 構成 本記事では、Rubyやawspecは以下のバージョンを使用しています。 Ruby: 2.2.4 awspec: 0.37.7 対応しているAWSリソース awspecでテストできるAWSリソースの代表的なものは以下の通りです。 詳しくは公式ページをご参照下さい。 https://github.com/k1LoW/awspec/blob/master/doc/resource_types.md EC2 RDS ELB Elasticache IAM VPC SecurityGroup インストール gemパッケージをインストールします。 本記事では単純にgemでインストールしていますが、Bundlerなどで管理するほうがおすすめです。 $ gem install awspec 次に任意のディレクトリに移動し、以下のコマンドで必要なファイルを生成します。 $ awspec init initを実行すると、以下の様なディレクトリとファイルが生成されます。 . ├── Rakefile └── spec └── spec_helper.rb 構成自体はServerspecとほぼ同じです。 specディレクトリ以下に、各テストを書いていきます。 specファイルを書いてみる specディレクトリ以下に リソース名_spec.rb という名前でファイルを作成します。 ここではEC2のspecを書いてみます。 $ vi spec/ec2_spec.rb require 'spec_helper' describe ec2('server1') do it { should exist } it { should be_running } its(:instance_id) { should eq 'i-00000000' } its(:image_id) { should eq 'ami-c8xxxxxx' } its(:private_dns_name) { should eq 'ip-10-0-0-95.ap-northeast-1.compute.internal' } its(:public_dns_name) { should eq 'ec2-52-xxx-xx-xxx.ap-northeast-1.compute.amazonaws.com' } its(:instance_type) { should eq 'c3.large' } its(:private_ip_address) { should eq '10.0.0.95' } its(:public_ip_address) { should eq 'xx.xxx.xx.xxx' } %w{ hoge-access-sg huga-access-sg default-sg }.each do |sg| it { should have_security_group(sg) } end it { should belong_to_vpc('vpc-0') } it { should belong_to_subnet('front-subnet-a') } it { should have_eip('xx.xxx.xx.xxx') } it { should have_ebs('vol-xxxxxxxx') } it { should have_ebs('Created for server1') } end このように、Serverspec(RSpec)ライクにテストが書けます。 Generate ただ、既存リソースを全て手で起こすのは苦行だと思います。 awspecには既存のリソースをテストに起こしてくれる機能があるので、使ってみましょう。 AWSのCredentialは登録されているものとします。 また、IAMで各リソースのRead権限が付与されている必要があります。 $ export AWS_REGION=ap-northeast-1 $ awspec generate ec2 vpc-xxxxxxxx --profile staging >> spec/ec2_spec.rb ※ vpc-xxxxxxxxは実際に存在するVPC IDを指定して下さい。 実行 上記で書いたテストを実行してみましょう。 Rakefileがある場所まで移動し、以下のコマンドを実行します。 $ export AWS_REGION=ap-northeast-1 AWS_PROFILE=staging $ rake spec 以下のように結果が出力されます。 ec2 'server1' should exist should be running should have security group "hoge-access-sg" should have security group "huga-access-sg" should have security group "default-sg" should belong to vpc "vpc-0" should belong to subnet "front-subnet-a" should have eip "xx.xxx.xx.xxx" should have ebs "vol-xxxxxxxx" instance_id should eq "i-00000000" image_id should eq "ami-c8xxxxxx" private_dns_name should eq "ip-10-0-0-95.ap-northeast-1.compute.internal" public_dns_name should eq "ec2-52-xxx-xx-xxx.ap-northeast-1.compute.amazonaws.com" instance_type should eq "c3.large" private_ip_address should eq "10.0.0.95" public_ip_address should eq "52.xxx.xx.xxx" Finished in 0.48842 seconds (files took 2.11 seconds to load) 16 examples, 0 failures なんとも見やすい! ちなみに失敗した時は以下の様な出力になります。 ec2 'server2' should exist should be running should belong to vpc "vpc-0" should belong to subnet "front-subnet-a" should have eip "xx.xx.xx.xx" should have ebs "vol-xxxxxxxx" instance_id should eq "i-xxxxx" (FAILED - 1) image_id should eq "ami-c8xxxxxx" private_dns_name should eq "ip-10-0-10-96.ap-northeast-1.compute.internal" public_dns_name should eq "ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com" instance_type should eq "t2.large" (FAILED - 2) private_ip_address should eq "10.0.10.96" public_ip_address should eq "xx.xx.xx.xx" Failures: 1) ec2 'server2' instance_id should eq "i-xxxxx" Failure/Error: its(:instance_id) { should eq 'i-xxxxx' } expected: "i-00000000" got: "i-12345678" (compared using ==) # ./spec/ec2_spec.rb:6:in `block (2 levels) in <top>' 2) ec2 'server2' instance_type should eq "t2.large" Failure/Error: its(:instance_type) { should eq 't2.large' } expected: "t2.large" got: "t2.small" (compared using ==) # ./spec/ec2_spec.rb:10:in `block (2 levels) in <top>' Finished in 0.61169 seconds (files took 2.87 seconds to load) 15 examples, 2 failures Failed examples: rspec ./spec/ec2_spec.rb:6 # ec2 'server2' instance_id should eq "i-xxxxx" rspec ./spec/ec2_spec.rb:10 # ec2 'server2' instance_type should eq "t2.large" 上記では、以下の2項目が失敗しています。 server2のインスタンスIDが、テストケースと実際の値で差異がある インスタンスサイズが、テストケースではt2.largeだが、実際はt2.smallとなっている このように、テストに失敗しても簡単に追うことが可能です。 YAMLに落としてみた テスト対象が増えてくるとメンテナンスコストが高くなる可能性があります。 頻繁に修正が行われるのを考慮し、YAMLを読むようにしました。 まず、Rakefileに以下を追加します。 $ vi Rakefile require 'yaml' 次にYAMLを記述します。 $ vi config.yml ec2: - name: "server1" instance_type: "t2.micro" security_groups: - "hoge-access-sg" - "huga-access-sg" - "default-access-sg" eip: "52.xxx.xx.xxx" private_ip_address: "10.0.0.95" subnet: "front-subnet-a" - name: "server2" instance_type: "t2.micro" security_groups: - "hoge-access-sg" - "huga-access-sg" - "default-access-sg" eip: "52.xxx.xx.xxx" private_ip_address: "10.0.0.96" subnet: "front-subnet-c" specヘルパーを修正します。 YAMLで読んだ値を @properties という変数に格納し、各specファイルから参照できるようにします。 $ vi spec/spec_helper.rb require 'awspec' require 'yaml' Awsecrets.load(secrets_path: File.expand_path('./secrets.yml', File.dirname(__FILE__))) @properties = YAML.load_file("config.yml") 最後に、各specを修正します。 今回はEC2を例として、以下に記述します。 $ vi spec/ec2_spec.rb require 'spec_helper' properties = @properties properties['ec2'].each do |ec2| describe ec2(ec2['name']) do it { should exist } its(:instance_type) { should eq ec2['instance_type'] } its(:private_ip_address) { should eq ec2['private_ip_address'] } ec2['security_groups'].each do |s| it { should have_security_group(s) } end it { should belong_to_subnet(ec2['subnet']) } it { should have_eip(ec2['eip']) } unless ec2['eip'].nil? end end 悩んだポイント インスタンスロールに対応していない awspecが使用しているawsecretsというgemが、 インスタンスのIAMロールに対応しておらずcredentialが存在しない環境では使用できませんでした。 こちらはawsecretsにPullRequestを行う予定です。 CloudFrontなど一部のリソースに対応していない 特にCloudFrontはほしかったです…。 こちらも時間があるときに書いてみます。 まとめ これまで、アプリケーションやOS/ミドルウェアのテストはありますが、AWSリソース自体のテストはあまり一般的ではありませんでした。 awspecの登場により、より簡単に構築したリソースのテストが可能となりました。 やはりテスト大事ですね!
こんにちは。広告システム開発部の瀬川です。 medibaの開発プロジェクトでは スクラムを採用するチームをよく目にします。 私も開発メンバーとしてスクラムに参加してきましたが、 利用するツールに迷っていた時期がありました。 今回はそんな時期に出会った、 『オープンソースのスクラムツール「Taiga」をAmazon EC2で使えるようにするまで』 をご紹介させていただきます。 なぜTaiga? 今まで使ったWebツールの詳細については控えさせていただきますが みなさんはスクラムツールを使ってきて、 こんな思いを抱いたことありませんでしたか? ツール利用料がなんとなく高い気がする。。 設定項目が多すぎる。。 画面が味気ない。。 私は上記のような不満を多少なりとも感じていました。 一見、スクラムを実行するのに上記項目は無関係に思われるかもしれませんが、 「使いたくなるツール」は きっとスクラムを継続することを後押ししてくれると考えました。 「参加したくなる会議の仕組み」と同様に大切なことではないでしょうか。 したがって、 料金的に敷居が低く 触っていて楽しい モチベーションをあげてくれる そんなツールを探していました。 Taigaとは? そんなときに出会ったTaigaの特徴は オープンソース 無料で使える(有料プランもあり) シンプルに使える Best Agile Tool 2015 授賞 と公式ページに記載があります! その他の特徴については オシャレな公式ページで、是非チェックしてください! https://taiga.io この公式ページを見たときに「なにこれ、カッコいい!」と思い、 「使ってみたい欲」がぐぐぐっと高まりました! いざ!インストール! さて、それではインストールしてみましょう。 Taigaは ネットワーク経由で利用できるプランだと1プライベートプランつき25人まで無料 です。 (詳細は 料金表参照 ) ですが、今回はカスタマイズも視野に入れて、 AWSのEC2(ubuntu)に GitHubからソースをcloneし、Amazon EC2にインストールしてTaigaを利用 しましょう! これならAWSの利用料金だけを考慮すればよいですね。 (この場合の注意事項は後ほど記述します。) 準備するもの AWS EC2 (ubuntu 14.04 ) こちらは割愛いたします! 特別な設定はいりません。t2.microで作成しました。 ※Amazon EC2でubuntu利用する場合、デフォルトユーザーは「ubuntu」なのでご注意ください。 ssh -i ~/.ssh/taiga.pem ubuntu@ec2-12-345-678-901.ap-northeast-x.compute.amazonaws.com インストール手順 Taigaのインストールに必要なのでgitをインストールします。 sudo apt-get install git 次にTaigaのインストール用スクリプトをcloneします。 git clone https://github.com/taigaio/taiga-scripts.git そしてインストール用のシェルを実行します。 cd taiga-scripts bash setup-server.sh インストールは以上です。 こちらがアクセスした際の画面です。 ID/PASSWORD: admin/123123 が管理者の初期設定となっております。 早速 プロジェクトを作る ↓ スプリントを作成する ↓ ユーザーストーリーを作る ↓ タスクを作る ↓ ユーザーストーリーをスプリントに登録する の手順でやってみましょう! まずプロジェクトを作成します。 KANBANだけでよければKANBANを、 そうでなければSCRUMを選択してください。 ちなみにSCRUMでもKANBANモジュールを後で追加できますのでご心配なく。 こちらがプロジェクトのトップ画面です。 この画面で、 プロジェクトゴールまであと何ポイントか 優先度の高いユーザーストーリーはどれか 今のスプリントのポイント数と消化されたユーザーストーリー などがわかります。 次にスプリントを作成しましょう。 sprint1、続けてsprint2の2つを作ってみます。 スプリントの作成フォームでは「last sprint is xxxx;-)」のように前のスプリント名がサポート表示されるのがちょっとだけ嬉しいです。 こちらがsprint1、2を作成したあとのプロジェクトトップ画面です。 次にユーザーストーリーを作成してその中の必要なタスクを作り、 sprint1に登録しましょう! ユーザーストーリー作成画面では タイトル ストーリーポイント 詳細 を入力します。他にもタグ付けやファイル添付もできます。 次にユーザーストーリーに必要なタスクを作成します。 タスクの作成が完了したらバックログからsprint1に移動しましょう。 作成したユーザーストーリーは一旦バックログに追加されます。 バックログからスプリントへの移動はドラッグ&ドロップで可能です。 複数件の移動も対象ユーザーストーリーのチェックボックスを チェックしてドラッグ&ドロップします。 これでスクラムを開始する準備が整いましたね! また、Taiga内でのアクションに応じて加点され、 得点の高いメンバーには称号?がもらえます!スプリントの終わりに話題になることもあります。 また、ユーザーストーリーに対して必要な項目を追加設定できます。 (カスタムフィールド) 例えばTaigaにはタイムトラッキングの機能が用意されていません。 その場合、カスタムフィールドの利用を方法の一つとしてTaigaは提案しています。 Why is there no Time Tracking? 注意事項 まず、taiga-script、ASP版によらず Taigaは日本語対応がされていません。説明などは全部英語です。 日本語入力はなんとかできます。 そして taiga-scriptでのインストール時の注意事項 ですが、 その一つに The installation is not 100% ready for production. とあります。 いいですよ、無料で使わせてもらうのですから。。。 さぁ、いざチームメンバーをご招待!!… あれ?招待メールが飛びません!! せっかく入れたのにこのままでは一人ぼっちスクラムです。 早速修正していきましょう。 招待メールが飛ばない ~解決方法~ 調べてみるとMTAがインストールされていないので、 postfixをインストールします。 sudo apt-get -y install postfix そして設定ファイル taiga-back/settings/local.py を書き換えます。 cd ~/taiga-back/settings vi local.py 修正前) #EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" #EMAIL_USE_TLS = False #EMAIL_HOST = "localhost" #EMAIL_HOST_USER = "" #EMAIL_HOST_PASSWORD = "" #EMAIL_PORT = 25 修正後) EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_USE_TLS = False EMAIL_HOST = "localhost" #EMAIL_HOST_USER = "" #EMAIL_HOST_PASSWORD = "" EMAIL_PORT = 25 そしてnginxとcircusで動いているので circusを再起動すると招待メールが送れるようになりますが 詳細メール記載の登録用URLのドメインが localhost:8000になっているので下記修正も同時にやりましょう! 修正前) # This should change if you want generate urls in emails # for external dns. SITES["front"]["domain"] = "localhost:8000" 修正後) # This should change if you want generate urls in emails # for external dns. SITES["front"]["domain"] = "EC2のドメイン" そしてcircusの再起動。 sudo service circus restart これで招待メールが送れるようになりました! こちらが招待されたユーザのサインアップ画面です。 Taiga is a project management platform for agile developers & >designers and project managers who want a beautiful tool that makes >work truly enjoyable の通り、Beautifulですね。 おわりに 無事にインストールできましたか? 他のツールが中々見つからなくてもやもやしてる方! AWSを利用できる環境であれば 簡単に始められるのでぜひ試してみてください。 すでにもっとこうしたい!!という改善点がありますので、 せっかくのオープンソースですからチームにあったカスタマイズに チャレンジしていきたいと思います。
メディアシステム開発部の北田です。 auスマートパスのサーバサイド開発を担当しております。 担当サービスのQCDと個人的な問題意識から、 Go言語 の導入に取り組んでいます。 今回は、 Vimmer がGo言語と向き合う際のtipsについてまとめました。 はじめに 無用な混乱を避けるため、注意事項及び前提条件を設けました。 はじめにお読みください。 ソースコード 本稿で利用するソースコードは、 GitHubの公開リポジトリ に格納してあります。 断りがない場合、カレントディレクトリは、以下の通りです。 $ pwd /path/to/mediba-kitada/mbo/2016first/blog_vim-go 省略したこと Vim及びGo言語の概要については省略しています。 参考にした書籍 Software Design 2016年5月号 スターティングGo言語 以下のツールを利用しますが、概要については省略します。 direnv neobundle neocomplete サポートする環境 Mac(OS X)オンリーです。以下のバージョンをサポートしています。 Yosemite El Capitan 以下のVimをサポートしています。 ディストリビューション バージョン 備考 MacVim 7.4 筆者環境は、luaサポートをonにしてあります 利用するVim pluginは、以下の通りです。 名称 バージョン 備考 vim-go master - 以下のGo言語をサポートしています。 1.1以上 以下のshellをサポートしています。 zsh 想定読者 上記を踏まえ本稿の想定読者は、以下の通りです。 Go言語のチュートリアル をやってみて、何かを見出した Go言語と長くお付き合いしたい一般的なVimmer 私です。 導入 vim-go をインストールしていきます。 vim-goは、Go言語向けVim pluginで他のpluginに比べ 圧倒的な支持 を得ています。 neobundleを用いて以下の様に導入していきましょう。 $ vi ~/.vimrc " golang NeoBundle 'fatih/vim-go' " コマンドモードで.vimrcをリロード :source $MYVIMRC " コマンドモードでNeoBundleInstall :NeoBundleInstall 試運転をしてみましょう。 フォーマットが出鱈目なエントリーポイントを用意し、セーブしてみます。 # フォーマットが出鱈目なエントリーポイントを開く $ vi src/main/main.go " コマンドモードでGoFmt :GoFmt vim-goの :GoFmt コマンドでフォーマットされていることがわかります。 カスタマイズ ツール群のインストール vim-goは、 :GoInstallBinaries コマンドを用いてGo言語での開発に便利なツール群をインストールしてくれます。プロジェクトで開発するパッケージとvim-goで利用するパッケージの混同(同一ディレクトリに配置される)を避けるため、shellで環境変数GOPATHを利用して、インストールしていきましょう。 # 共有のGo言語環境の各ディレクトリを作成 $ mkdir -p {$HOME/go,$HOME/go/bin,$HOME/go/pkg,$HOME/go/src} # shellの設定ファイルにGOPATHを設定 $ vi $HOME/.zshrc # 共通のGo言語環境変数とそのパス export $GOPATH="$HOME/go" # ツール群のバイナリファイルが格納される export $GOBIN="$GOPATH/gin" # shellの設定を更新 $ source $HOME/.zshrc Vimを起動し、 :GoInstallBinaries コマンドでツール群をshellの設定ファイルで指定したパスにインストールします。 # プロジェクトのルートディレクトリ(.envrcが格納されているディレクトリ)から離れる $ cd $HOME # Vimを起動しコマンドモードで GoInstallBinaries を実行 $ vi :GoInstallBinaries # ツール群が共通のGo言語環境のパスにインストールされていることを確認する $ tree $GOPATH/bin /Users/mediba-kitada/go/bin ├── asmfmt ├── errcheck ├── gocode ├── gogetdoc ├── goimports ├── golint ├── gometalinter ├── gorename ├── gotags ├── guru └── motion ツール群の試運転をしてみましょう。animalsパッケージのmonkey.goを修正します。 $ vi src/animals/monkey.go " コマンドモードでGoImports :GoImports vim-goの :GoImports コマンドでfmtパッケージがインポートされていることがわかります。 vim-goの設定 デフォルトではシンタックスハイライトがオフになっていますので、設定ファイルを用いて設定をカスタマイズしていきましょう。 :GoFmt コマンドを実行した際の挙動もカスタマイズしてみます。 $ vi $HOME/.vimrc " vim-go "" mapping """ go runのキーマッピング au FileType go nmap gr (go-run) """ go testのキーマッピング au FileType go nmap gt (go-test) "" highlight let g:go_hightlight_functions = 1 let g:go_hightlight_methods = 1 let g:go_hightlight_structs = 1 let g:go_hightlight_interfaces = 1 let g:go_hightlight_operators = 1 let g:go_hightlight_build_constraints = 1 "" GoFmt時にインポートするパッケージを整理(GoFmtはファイル書き込み時に自動的に実行される) let g:go_fmt_command = "goimports" 試運転をしてみましょう。先ほどと同様にanimalsパッケージのmonkey.goを修正します。 $ vi src/animals/monkey.go " バッファの内容をファイルに書込 :w ファイル書き込み時に :GoFmt によるフォーマットと、 :GoImports コマンドによるパッケージのインポートが実行されていることがわかります。 テストも実行してみましょう。 $ vi src/animals/elephant.go " テストの実行 \gt 自動補完 neocompleteをインストール、設定していれば自動補完もかっこ良くなります。 課題 本稿では対応出来ていないvim-goのカスタマイズについて簡単に触れておきます。 Tagbar ctagsを適切に設定することで関数の一覧バッファをサイドビューとして表示し、タグジャンプにも利用出来ます。 Neovim 対応 vim-go開発者のfaithさんもNeovimを利用しだした とのことですが、まだうまく動いておらず、ベータとして提供している様です。 おわりに Vimmer向けにGo言語開発環境の実践的な内容をまとめてみました。ここでは触れていませんが、ビルドコマンドも提供されており、vim-goさえあればVimmerのGo言語開発は何とかなるのではと見込んでおります。これは、シンプルな規約に沿ってデザインされたGo言語の恩恵のひとつなのかもしれません。 弊社では、バックエンド(サーバサイド)エンジニアを 鋭意募集 しています。Go言語の他にもモダンな技術の導入には前向きに取り組んでおりますので、腕自慢の方はぜひご応募ください。
こんにちは。制作部の西野です。 mediba制作部では、制作過程でデザインレビューを取り入れています。制作したデザインに対して、そのプロジェクト内のメンバーだけではなく、プロジェクトに携わっていないエンジニア・デザイナーが第三者からの視点でデザインに対してコメントをし合っています。そして、デザインレビューをする際に「 InVision 」というwebサービスを使っています。もう、すでに導入されている会社も多くあると思いますが、名前は聞いたことはあるが、まだ実は使う機会がなくて使ったことがない方も多くいらっしゃるのではないでしょうか?今回はその「InVision」についてご紹介いたします。 InVisionとは? 無料でも使える、プロトタイピングツールです。 webブラウザを用いて、簡単にプロトタイプを制作することや、ファイルを共有することができます。 なぜ InVisionを使うようになったのか? Invisionを使うようになった理由は3つあります。 1つに、簡単にコメントが残せること。 2つに、簡単にデザインデータを共有できること。 3つに、簡単にプロトタイプが作れること。 とにかく簡単で便利なツールです。 以下で詳しく説明いたします。 InVisionのここが便利! 1.簡単にコメントが残せる InVision導入前、デザインレビュー時のコメントについてこんな不便がありました。 『page_01.pngの青いボタンのところですが…』 『メインイメージの下のタイトルとキャプションのマージンなんですが…』 このように、指摘箇所について文字で説明することとなってしまい、伝える側/受け取る側ともに 指摘箇所が伝えにくい、わかりにくい こととなってしまっていました。 しかしInVisionでは、場所を直観的に指定してコメントすることができます。 共有されたURLにアクセスし、COMMENT MODEをONにします。そして、画像の上でクリックをするとコメントを残すことができます。 コメントの色を3色から選ぶことが出来ますので、チーム内でルールを決めて「絶対に直した方がいいこと」、「メモ」、「相談、提案」、のようにコメントの用途別で色を使うことも便利かもしれません。また、tour pointを選択するとpreviewモードで閲覧する際にアニメーションが付きます。特に注意を促したい時などに利用できます。 さらにペンのアイコンを押下することでペイントツールやシェイプツールに切り替わります。コメントだけではなく柔軟にレビューすることが出来ます。 また、コメントが複数つきやりとりが長くつづくと、修正したかどうか?/なぜこのように変更をしたのか? コメントに対してのアクションが見えづらく、追いづらく なってしまいがちです。こういった問題もInVisionでは解決することができます。 コメントの「Marked resolved」のチェックボックスをチェックすることで、ステータスを解決済みに変更することができます。 課題の状態を管理することができ、また残課題について確認しやすいUIとなっています。 コメント毎に、コメントと画像が 登録したメールアドレスに送信されるのも、やり取りの履歴を確認する上で便利な点の一つです。 2.簡単にデザインデータを共有できる InVision Syncをインストールすると、ローカル環境にあるデータをInVisionサーバーに同期することができます。データの種類は、.psd, .sketch, .pdf, .png, .jpg, .gifに対応しています。 保存するたびに同期する設定にもできるので、デザインデータを格納する手間が省けたり、共有し忘れることもなくなります。 さらに、同期されるたびに履歴が残るので、前のバージョンにも簡単に戻すことができます。 ※あまりないとは思いますが、複数人で同じファイルを編集する際は、一番最後に保存されたデータがマスターデータになってしまうので上書きし合わないように注意が必要です。しかし、履歴を辿ることもできるので、注意さえしていれば大丈夫だと思います。 またInVisionが提要している「InVision Sync」だけではなく、「Dropbox」や「Google Drive」などの様々なアプリケーションと連携していますので、環境に応じて同期方法が選べることも魅力の一つです。 3.簡単にプロトタイプを作れる スマートフォンサイトを作る際、PCの画面上で見ていた印象と、実機で確認した時の印象がなんだか違う!なんてことがよくあると思います。そのため、デザインの段階でも実機の確認は必須なのですが、毎回画像を書き出してテスト用のサーバーにアップロードするのはちょっと面倒です。InVisionはそんな手間を省いてくれます。 デザインデータをアップロードするだけで、プレビュー用のURLが作られます。嬉しいことに、PSDデータからの書き出しはアートボードごとにInVisionが勝手に書き出してくれるので、先ほど紹介した「InVision Sync」を使用していれば、保存をするだけで変更が即時反映されます。iOSでは専用アプリで確認することができます。 またモバイルブラウザでも同じようにデザインを確認することが出来ますので、アプリを入れる手間なく実機確認することもできます。   また、もっと実機で動きのイメージを見たい人にもオススメです。 リンクをつけたり、アニメーションを指定することもできます。 BUILD MODEを選択したのち、アニメーションやリンクをつけたいエリアを選択し、動きを指定するだけで簡単に動きのあるプロトタイプが出来上がります。 簡単なプロトタイプを作るには十分な種類の、動作タイミング/アニメーションの詳細指定があります。 まとめ プロトタイプツールとしても、デザインレビューのツールとしても非常に便利なwebツールです。 簡単であるため、学習コストがあまりかからずに導入できると思います。ローカル環境とInVisionサーバーの同期方法の中にAdobe Creative Cloudの連携も示唆されており、ますます便利な機能が追加されていくことを期待したいです。 実は面倒だと思っていた、ちょっと不便だと思っていたことを解決してくれるサービスです。 InVisionを知っていてもまだ使ったことがない方、こんなに便利な機能がたくさんあります。百聞は一見に如かず。ぜひ一度試してみてはいかがでしょうか?
こんにちは。制作部の苅部です。 今回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との比較などもやってみたいと思います。