JAZUG沖縄のCognitive Servicesハンズオンに参加しました。

2017年12月3日にGwave Incubateで行われた、Cognitive Servicesのハンズオンに参加してきました。

講師としてMicrosoftの大森彩子さんがきていただき、まず最初にCognitiveServiceとは何ぞや?という軽い説明があり、その後はハンズオンで参考にする手順書の通りにツールの説明をして頂いてすぐハンズオンに入りましたが、今回ありがたかったのは、ハンズオンの資料をC#版とnodejs版の2パターン用意していただいていたことで、そのおかげでC#書いたことのない僕でも参加することができました^^

ハンズオンの内容はAzureのcustomvision.aiを使って写真から食べ物を判定するモデルを作り、それをBot Frameworkから使って画像をチャットに上げるとその食べ物がなにか判定するbotを作るということをまずやってみて、そのあとに自分のアイディアをもとにオリジナルのbotを作ってみるという内容でした。

ハンズオンの最後の方では参加者が作ったオリジナルボットの発表が行われ、インスタジェニックな写真を判定するボットや犬に関するクイズの答えを写真で投稿して正解かどうか判定するボット、他にはあじとやというカレー屋さんのカレーを見分けるボットなどいろんなおもしろいボットが発表されました。

ちなみにぼくは、人の画像をアップしてもらってその写真が自分の子だった場合だけ大絶賛してくれるという「親バカBot」を作りました。

f:id:arakaji-yuu:20171203074635p:plain

f:id:arakaji-yuu:20171203074649p:plain

ハンズオンが終わり懇親会で他の参加者ともたくさん話したんですが、「勉強会に参加するときに話聞くだけだと懇親会行かないとなかなか他の参加者や講師と交流する機会がないけど、ハンズオンはそれだけでも面白いしハンズオンしながら他の参加者や講師に相談したりしながら交流できるので楽しい」というのを良く聞きました。

話を聞くのもいいけど、やっぱり自分でコードを書きながら、みんなでワイワイやるのは楽しいよなー^^

今回企画してくれたJAZUG沖縄と講師してくださった大森さん、会場提供してくれた琉球インタラクティブさんには感謝です! ありがとうございました!!

情報共有の価値観の違いとマネジメント手法の違いはリンクする

組織内での情報共有をどのレベルでするのかは、どのような組織でありたいか、そしてどのようなマネジメント手法を良しとするのかにリンクするな〜と最近考えていたのでそのまとめです。

オープンな情報共有とマクロマネジメント

会社のメンバーがそれぞれ目標達成するための方法を自分で考えて実行できる組織にしたいとする。

そのためにはオープンな情報共有の文化が必要。

なぜなら、手に入る情報が部署や役職によって差がある場合、その情報が手に入らない人は正しい判断ができないからだ。

逆にいうと、オープンな情報共有の文化を作れば、マネジメントは会社全体の方向性を示すこととなり、それを達成する方法は各々のチーム、個人が考えて行動していくことなる。

個人が考えて行動するためマネージャーの思った通りに行かないこともある。ただその個人に裁量があるため、意思決定のスピード、実行のスピードも速くなり、マネージャーの技量を超えた成果を出せることもできるだろう。

クローズドな情報共有とマイクロマネジメント

逆にタスクや戦略などはすべてマネージャー層が決めて、それを無駄なく早く実行できる組織にしたいとする。

その場合はオープンな情報共有の文化は必要なく、タスクの共有や進捗の共有のみでよくなる。

なぜなら、あらゆることをドキュメントに残して共有するのは手間がかかるし、すべての情報に誰もがアクセスできるようになると皆が意思決定に参加可能になるため考える時間が発生する。そうすると実行することに迷いや混乱が生まれる可能性があるからだ。

組織全体の情報を把握しているのがマネージャー層のみになるため正しい判断ができるのはマネージャーということになり、他のメンバーはその判断の実行のみ集中することができる。

それによって情報共有が必要なのはマネージャー層のみになるため情報共有するコストは下がるが、タスク決めから進捗管理や細かい判断まですべてマネージャがやらないといけないためマイクロマネジメントすることになる。

マイクロマネジメントするためマネージャー層が決めたことを確実に実行できる可能性が高まるし予期しないことが起きる心配も少ない。 ただ逆にいうと想定を超えるような成果が発生することもないといえる。

個人としては...

どちらにもメリット・デメリットあるし、その組織がどうありたいかを元にどうするべきか決めたらいいと思う。

ただ個人としては、自分の裁量が増えるような体制の方が成果は出しやすいしモチベーションが上がりやすい。 あと優秀な人(もしくは優秀だと思っている人)ほど自分で意思決定したいと思うので、マイクロマネジメントな組織で優秀な人を集めるには相当強いリーダーシップがないといけなくて、そっち方が組織の成果を高める上で、難易度が高いんじゃないかと考えてる。

子育てはじめて約2ヶ月が立ちましたので、近況を記録

息子が生まれて約2ヶ月がたちました。 いろいろ思うことや考えていることがあるので、まとめておきます。

沐浴は結構たいへん

赤ちゃんをお風呂に入れることを沐浴といって、いまはボクが担当しています。 沐浴はベビーバスに入れて行っているのですが、赤ちゃんが思っているよりも重くて片手で支えて片手で洗うのが結構たいへんです。

使っているベビーバスの頭の部分にクッションがついていて安心してベビーバスに寝かしながら洗えるので、これを買って正解でした。

永和 新生児用ベビーバス 498111

永和 新生児用ベビーバス 498111

料理をするようになりました。

妻の方がどうしても赤ちゃんの世話の負担が大きくなるので、代わりにボクがご飯をつくるようになりました。 いままで生きてきてまともに自炊することがなかったのですが、いまはほぼ毎日自炊しています。

ただ知っているレシピはもちろんほとんどないので、kurashiruという料理アプリを使っています。

このアプリが比較的簡単でかつ美味しいレシピを動画で見れるので、料理をやったことがないボクでもなんとか楽しく料理が出来ています。 やっぱり手順を動画で見れるっていうのは、普段ほとんど料理をしていない人にとっては料理のハードルが下がるので良いのですねw

いま一番使っているアプリで中の人になりたいぐらいですw

子育て中に会社での残業は、まあできない

上で書いたように子供の沐浴と自分のご飯をつくるのを家に帰ってきてからやっているので、いま基本19時くらいには帰宅しています。 残業したとしても20時くらいに帰るのですが、それでもだいぶ遅くに帰ってきた感じです。

しかも子供を寝かしつけたあとかなり静かにしていないと起きちゃうので、夜遅く帰ってくるのもアウトです。

その状態で遅くまで会社に残って仕事をする生活はボクには出来ないなと実感しています。

それだけやってもやっぱり妻の方が負担は大きく、夜中に子供が起きちゃうときの世話はボクを寝かしておいてくれて、妻だけで対応してくれています。

そのおかげでなんとか仕事には支障はきたさずに生活出来ていますが、今の時代に子育てや家事を女性に任せっきりするような男になりたくないし、何よりそんな姿を息子にも見せたくないので、もっとパートナーとして上手く家事を分担していきたいと考えています。

あとエンジニアらしく、テクノロジーを使って効率化していきたいですね。

コードを書く時間や勉強時間をどのように作っていくか

仕事をする時間や自分が自由に使える時間がやっぱり減ってしまうので、どうしてもコードを書いたり新しいことを勉強する時間が少なくなってしまいます。

それでもやりたい個人プロジェクトや技術についての勉強なんかもやっていかないと楽しくないので、どうその時間を確保するかが今の課題です。

仕事の効率化を上げて仕事の時間で勉強したり、Code Write Everydayなんかをやったりして上手くInputとOutputの効率を上げていかないといけないですね。

子供が生まれて自然に長期的な視点を持てるようになった

IT業界のベンチャーやスタートアップっていう、3ヶ月先すらどうなっているかわからないとていう環境にずっといる影響か、10年後20年後のことを考えることがほとんどなかったんですが、子供が生まれるとその子が成長する10年後20年後を自然に考えるようになりました。

それまでは自分のピークは30代くらいだと思っていて、それまでに大きな成果をださないとという考えだったんですが、子供が大人になったときに「お父さん昔はこんなことやってすごかったんだぞ」なんて昔話をせずにそのときに一番すごい状態に持っていきたいと思いました。

そのためにはエンジニアとして流行りを追うばかりでなく、今後は基礎をしっかり固めたり、難しいが価値のある挑戦をどんどんしたりして自力をしっかりつけていきたいと思うし、エンジニアリングだけでなくプロダクトマネジメントや経営のところまで進んでいきたいと思うようになってきました。

いまの仕事をしながらプロダクト作ってそのマネジメントとかやっていけるといいですが、、、がんばります^^;

沖縄のプログラマーコミュニティ「Java Küche」の会長をさせて頂くことになりました。

2017年10月7日に行われたイベント「いま注目のMicrosoft最新テクノロジーをキャッチアップ ~ Azure、Cognitive Services、Xamarin ~ - Java Küche | Doorkeeper」の中でも報告させていただきましたが、沖縄のプログラマコミュニティ「Java Küche」の会長をさせて頂くことになりました。

Java Kücheは2006年7月から続く歴史あるコミュニティで、僕で4代目の会長になります^^

これから一年、他の役員の皆さんに支えてもらいながら、いままで繋いできたコミュニティの文化を継続させつつ、さらに沖縄のエンジニアの皆さんが楽しく、そして何より自分自身が楽しめるようなコミュニティ活動をしていきたいと思いますのでどうぞ宜しくお願い致します!

「いま注目のMicrosoft最新テクノロジーをキャッチアップ ~ Azure、Cognitive Services、Xamarin ~」というイベントで企画運営・登壇をしてきました。

2017年10月7日(土)にJava Küche主催の「いま注目のMicrosoft最新テクノロジーをキャッチアップ ~ Azure、Cognitive Services、Xamarin ~」と題した勉強会を企画運営し、登壇もしてきました。

java-kuche.doorkeeper.jp

なぜMicrosoftテクノロジーに関する勉強会を開いたのか?

Java Kücheというコミュニティでは1年に1回、自分たちの活動内容や予算をどのように使ったのか、そして次の一年をどのように活動するのかというに報告をコミュニティに行う「総会」というイベントを行うのですが、そのイベント時に一緒にどのような勉強会をしたいかというアイディア出しを行いました。

そのときに、近年のMicrosoftが発表してきた様々の技術についての興味があるがキャッチアップできるような勉強会が沖縄だとないことや、つい最近からXamarinやAzureなどのMicrosoftテクノロジーを仕事に使い始めたメンバーがいたことから、じゃあ自分たちでキャッチアップするための勉強会を開催しようと企画をしました。

イベント内容について

Microsoftのすべてのテクノロジーを網羅することは難しいため、Webアプリケーションを乗せるPaaSとしてAzure、様々なAI・機械学習の技術がサービスとして提供され気軽に利用できるCognitive Services、AndroidiOSのモバイルアプリをC#で両方同時に開発することができるXamarinの3つに絞ってセッションを用意しました。

登壇者にはエクセルソフトセールスエンジニアでXamarinコミュニティJXUG主宰でもある田淵 義人さん、日本マイクロソフト株式会社のテクニカルエバンジェリストの大森 彩子さんのお二人にわざわざ沖縄まで来ていただきました。

そしてAzureについては仕事でAzureを採用しているぼくが登壇させて頂きました。

Xamarin概要と活用方法

田淵さんの発表では、Xamarinが使われている事例やそもそものXamarinがどういうテクノロジーなのか、そしてXamarinの使い所などを話して頂きました。

個人的にはXamarin.FormsとXamarin.iOS / Xamarin.Androidとの使い分けのポイントが知れたのが良くて、やっぱりXamarin.Formsでサクッとクロスプラットフォームアプリが作れるときがXamarinの力が発揮できるユースケースなんだろうなと思いました。

はじめてのAzure App Service for linux と Web App for Containers

www.evernote.com

次は僕が「はじめてのAzure App Service for linux と Web App for Containers」という題名で登壇させていただきました。

今年の9月に公式版となったAzure App Service for linuxとWeb App for Containersについての概要と実際にAzureの管理画面を使いながらWeb App for Containersのアプリをデプロイしていくデモを行いました。

デモを選んだ理由ですが、沖縄県内のクラウド事情はAWSが一番多く、一部GoogleCloudPlatformを使っている方もおられるのですがAzureを採用している事例を聞いたことがなかったので、この機会に管理画面の使い方やAzure独自の概念についての説明を実際に動くデモを通してお伝えしたいと考えたからです。

実際に会場にいらしたら方はAzureを使っている方は32人中2~3人程度で、実際のデモを見せる事ができてよかったな〜と思います。 一部デモが動かないところがあって大成功とはいえないですが。。。^^;
次回また頑張ります。

AIを手軽に使える時代がやってきた!"人工知能パーツ" Congnitive Services 入門

大森さんの発表では、Cognitive Servicesで作られたアプリケーションのデモから、そもそも誤解されがちなAIとは何ぞやという話、そして多種多様なCognitive Servicesの紹介や利用例などを説明していただきました。

AIというと「たくさんデータをいれたら良い感じの答えを出してくれるすごいやつでしょ?」という勘違いをしてしまいがちだったんですが、AIの定義の正しい説明をしっかり説明していただき、ちゃんと理解をすることができたので面白かったです。

あとなによりも、AI時代の開発者のあり方「#早く面白いことやったヤツが優勝」というパワーワードを頂いたので、僕もCognitive Servicesを触ってみておもろいものを作っていきたいと思います^^*

さいごに

わざわざ沖縄まで講師としてやってきていただいた田淵さん、大森さんほんとにありがとうございました!!

沖縄に限らず地方だとどうしても技術の多様性が乏しく、今回のようなMicrosoftテクノロジーに精通した話を聞く機会が少なかったのでお二人にこのような機会をつくって頂けたのはとてもありがたかったです!

また、イベントに参加して頂いた方もありがとうございました!

これからも沖縄ではなかなか話をする機会が少ない登壇者をお招きして、沖縄にいるエンジニアがまず楽しく、そしてスキル上達の手助けにもなるイベントを企画していきたいと思いますのでどうぞ宜しくお願いします!

Webアプリケーションプログラムにおいて、「良いコードを書く」ための基本的な方針

自分はフレームワークを用いてWebアプリを書くことが多いのですが、その上で可能限り「良いコード」を書くように心がけています。

ただ、この「良いコード」というのがかなりの曲者で、プログラミングにおいてのイディオム的なことからオブジェクト指向の話、デザインパターンプログラミング言語においてのベストプラクティス、使用しているフレームワークのベストプラクティス、さらに広げるとドメイン駆動設計の話までかなり広い範囲が含まれてしまいます。

チームによっての技術レベルや目標としているものはもちろん違うので、基本的には現場現場で話し合って自分達の目指す「良いコード」を定義することが重要になるでしょう。

今回はMCVフレームワークを使ってWebアプリケーションを良いコードで書く上で、どの現場でも理解できて、かつ実践できるであろう私の頭にある「良いコードを書く」ための基本的な方針をまとめてみました。

まとめる上で、出来る限りオブジェクト指向エンタープライズアーキテクチャなどの用語を使わないように意識しています。

特に真新しいことはなにもなく、当たり前になっているとは思いますが、自分の頭の中を吐き出すためにこのブログを使おうかと。

基本的な方針

1.やっていることが違うコードは分離して名前をつける

管理画面などをMVCフレームワークで開発をしていてたまーにあるのが、おなじURLにPOSTされていても送信されてくるデータによって新規作成になったり、更新になったり、または違うテーブルのデータを更新する処理にかわったりすることです。これは管理画面を作る際に関連のある2つのテーブルのデータをユーザビリティのために一つの画面で更新できるようにした場合に発生します。

この時に愚直にコントローラー内の一つのアクションにすべての処理を書いていくと、コードが長くなりますし不用意に別の役割をしているコードに依存した処理を書いてしまいバグの温床になることがあります。

出来るだけ違うことをおこなうアクションは別にする。 もしUX上別に出来ない事がある場合はおなじアクションを叩くにしても内部上では別のメソッドを分離して、そのメソッドに処理を行わせるようにしています。

もちろんこれはコントローラーだけではなく、その他のプログラムにおいても同じです。

分離したメソッド名を適切な名前にすると、その名前をみるだけで何をしているのかわかるので可読性も上がります。

2. どこに責任を持たせるのかを決める

例えば商品を表現するDBのテーブルproductsがあり、各商品の識別子(ID)は企業名を表すアルファベット二文字(PKやITなど)とインクリメンタルの数値の8桁でないといけないというルールがあるとする。

そのようなルールがあったときに、商品の作成処理をおこなうControllerで毎回ID作成のためのロジックを書くのはコードの重複が増える上にプログラマーがルールを常に覚えていないといけないため問題です。

その問題を避けるため、商品の識別子を作成するためのメソッドを定義し、商品識別子の作成ロジックの責任はこのメソッドのみに持たせます。

責任を持たせるメソッドを定義することによりコードの重複が減り、かつビジネス上のルールをコードで表現することで可読性が上がります。

3. Web以外のインターフェースがあることを意識する

Webアプリケーション開発においてMVCフレームワークを使って開発をしているとき、注意をせずに開発をすると重要なビジネスロジックがコントローラー側に漏れていく事が多くあります。しかしControllerはWebのRequestとResponseが交わる場所になるので、ここにビジネスロジックを書くとWebのRequestとResponseに依存したプログラムになってしまいがちです。

そんなときに困るのが、同じような機能を提供する別の画面を作ったり、WebのUIではなくWebAPIを作ったり、またはコマンドラインのタスクを作ったりなど別のインターフェースから同一の機能を提供しようとしたときに、ロジックを抽出するのが難しくなってしまいます。

そのため、重要なビジネスロジックを書くときには常に今のUIとは別のUI・インターフェースから使われるときのことも意識し、Controllerから分離してコードを書きます。

4. 小さなプログラムを組み合わせて大きなプログラムを書く

大きなプロダクト一塊にして書くよりも小さなプログラムを作って細かく分割し、それを組み合わせて大きな機能を作ります。

そうすることで依存性も低く再利用性も高い小さいなコード群がたくさん生まれ、別の機能を作るときにそれらのコードを使ってより早く開発することができます。

おわりに

もちろん上記以外にも考えることは多いのですが、私が特に意識しているのがこの4つです。

こういうのを「単一責任の法則」的な法則名で意思疎通できると、話は早いんだろうなー。

PHPのループで書くと約30時間かかる大量の画像アップロード処理を、Clojureのcore.asyncで1時間以下に短縮できた話。

1つのVPSで動いている既存システムのAzureへの移行を進めています。

その上で既存サーバーに入っている画像ファイルをBLOBストレージ(Azureのオブジェクトストレージ、AWSでいうS3)に移すという作業が必要になりました。

最初はバックアップから画像ファイルをループでひとつづつアップロードする処理をPHPでシンプルに書きました。

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use MicrosoftAzure\Storage\Common\ServiceException;

// Create blob REST proxy.
$connectionString = "";
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString);

// imagesディレクトリから画像ファイルを取得
$images = getImagesFromDirectory('images');

 foreach($files as $file){
        $blob_name =  $path = "images/".$file;
        try {
            $content = fopen($path, "r");
            $blobRestProxy->createBlockBlob('imgcontainer', $blob_name, $content);
        }catch(Exception $e){
            echo "Exception Occers: ".$path;
            echo "\n";
            $code = $e->getCode();
            $error_message = $e->getMessage();
            echo $code.": ".$error_message."\n";
        }
}

最初は100枚だけで試してみたんですが、100枚をアップロードするだけで50秒ほどの時間がかかりました。 ただ画像ファイルはその時点で約23万枚ほどあり、単純計算でざっくり30時間ぐらいかかるとわかりました。

つらい。。。

30時間はつらい。。。

覚悟を決めて30時間ぶん回ししてもよかったのですが、「もし間違いがあった場合にまた30時間やるの辛い」 、「画像はいまも増えていくので再アップロードも必要になる」という理由から、なんとかもっと速く終わるようにプログラムを変えることにしました。

PHPは基本同期処理のプログラムなので、上記のやり方だとファイルアップロードの待ち時間の間処理が止まってしまいます。 その待ち時間がボトルネックだということは目に見えていたので、複数プロセス、非同期処理に変えてアップロードの待ち時間もバンバン他のファイルをアップロードするように変えれば確実に速くなります。

PHPでそのような処理を書く方法もあると思いますが、Clojureという言語のcore.asyncを使うと簡単に実装できるということを知っていたのでClojureで実装し直すことにしました。

core.asyncとは、Clojureで並行プログラミングをするときによく使われるライブラリです。 協調スレッドという軽量なスレッド(ネイティブスレッドではない)を作り、channel経由でスレッド間の通信を安全に行い非同期処理を行うプログラムを書くことができます。

golangを使ったことがある人には、goroutineと同じようなものだと考えるとわかりやすいと思います。

今回の画像アップロード処理をClojureのcore.asyncで書き直すと以下のようになりました。

(ns azure-storage-clj.core
  (:require [clojure.java.io :as io]
            [clojure.core.async :as as
             :refer [>! <! >!! <!! go chan buffer go-loop
                     close! thread alts! alts!! timeout]]
            [clojure.tools.logging :as log])
  (:import [com.microsoft.azure.storage CloudStorageAccount]))

(def connection-str "")

(def storage-account (CloudStorageAccount/parse connection-str))

(def blob-client (.createCloudBlobClient storage-account))

(def blob-container (.getContainerReference blob-client "imgcontainer"))

// 画像を置いてあるディレクトリ以下からファイルだけを取得する
(def filelist (filter #(.isFile %)
                      (file-seq (io/file "resources/images"))))

(defn image-upload [file]
  (let [f-source file
        filename (.getName file)
        blob (.getBlockBlobReference blob-container (str "images" "/" filename))]
    (.upload blob
             (new java.io.FileInputStream f-source)
             (.length f-source))))

(defn files-upload []
  (let [file-chan (chan 100) ;; バッファ100のチャネルをつくる] 
    ;; チャネルからファイルをとり、アップロードする協調スレッドを100個つくる
    (doseq [n (range 100)]
      (go-loop []
        (let [f (<! file-chan)]
          (do
            (log/debug "image-upload : " f) // ログ出力
            (image-upload f))) ;; 画像アップロード
        (recur)))
    ;; 画像ファイルのリストをひたすらチャネルに入れていく
    (for [f filelist]
      (>!! file-chan f))))

処理は以下のようなイメージです。

f:id:arakaji-yuu:20170524091829p:plain

この実装を朝の4時くらい起きて実装し、100枚、500枚と試してみて大分速くなることは確認できたので、 一気に全ファイル対象にして実行して二度寝へと向かいました(それが5時ごろ)。

7時くらいに目が覚めてPCの様子を伺うと、なんともう完了しているではありませんか。。。

ログを見ると約1時間程度で終わっていたようです。

感無量。。。。

Clojureを使うことで並行処理を簡単に実現できて、結果タスクにかかる時間も短縮できました。 やはりいろんなパラダイムの言語を知っておくとその時々の問題にあった手段を選べるのでいいですね。