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

第10回 Apache Cordova勉強会 @ Sony City Osakiに参加してきました!

今日は別件でアポがあって東京出張に来ていたのですが、上手くスケジュールが重なって(というか重ねて) 第10回 Apache Cordova勉強会 に参加してきました。

アシアル株式会社の田中さんによる「Vue 2についての発表(仮)」にはじまり、(株)ジェイアイエヌの佐藤さんによる「WEBエンジニアの可能性を広げるJINS MEMEのアプリ開発」、最後にソニーネットワークコミュニケーションズ㈱ の緒方さんによる「Cordova を使って本気で商用ハイブリッドアプリケーション開発をやってみた」という発表をして、その後に懇親会という流れでイベントは進みました。

みなさん興味深いお話をして頂きとても楽しかったのですが、個人的に一番インパクトがあったのが緒方さんよる発表で、開発したアプリを見せて頂いたのでしたがUI/UX、アニメショーンの動きなどがとてもハイブリッドアプリで作ったとは思えない程の完成度でとても衝撃を受けました。

Cordova使ったハイブリッドアプリの開発者なら誰もが「ハイブリッドアプリだからネイティブアプリのような体験は作れない」と諦めてしまいがちですが、「ユーザーにはネイティブもハイブリッドも関係ない、ユーザーの期待値はネイティブ」、「ハイブリッドアプリのメリットはネイティブをそれぞれ作る以上の生産性、そこを失ってはいけない」とクオリティと生産性を両立させるための高い基準を設定し、それを達成するために行ったさまざま工夫やノウハウを今回の発表や懇親会でのコミュケーションを通して共有して頂きました。

スケジュール、技術的制約、高い達成基準などがあるなかでしっかりとそれを達成するために開発に向き合う姿勢はエンジニアとして尊敬するとともに、現在のモバイルアプリの環境であればネイティブにも遜色ないUXをCordovaでも作れるという可能性を見せて頂けたとても良い会になりました。

Cordovaを使ったハイブリッドアプリ開発、がんばろ!!

2017年3月1日をもって、琉球インタラクティブからPayke(ペイク)に転職しました

2017年2月28日を持って4年間働いていた琉球インタラクティブを卒業し、Paykeに転職しました。 沖縄のネット系ベンチャーから沖縄のアプリ系スタートアップへの転職という形になります。

前職について

初めてプログラマーとして職をついたのがこの会社だったのですが、ECサイト、公共施設の予約システム、WordPressを使ったサイト構築、エンジニア向けイベント情報サービスの機能開発や沖縄の求人サービスの開発など様々なWebサービス開発にメインのエンジニアとして入る事ができ技術力をとても鍛える事ができました。

また最後の1年半はバイトや外部パートナー含めて最大10名のエンジニアチームのマネジャーも経験させて頂きました。

ベンチャー特有の急激な環境の変化や無茶振り、抜擢人事などはいろんな意味で大変なことも多いですが、 たとえ問題が起きても誰か一人の責任にせずに、誰もが協力して問題解決に取り組む文化、 プロセスは担当者に任せて結果重視で評価することで、様々なプロセスを担当者レベルでどんどん改善出来る文化、 結果を出している人は報酬やランクアップを通して積極的に評価する文化などは 自分のこれからのキャリアを作る上での大事な下地になったともに、個人的にとても働きやすい会社でした。

最終出社日の記念写真 f:id:arakaji-yuu:20170309114130j:plain

自分は新たなチャレンジのために卒業しましたが、もし沖縄でもベンチャーの荒波に揉まれてジェットコースターのようなキャリアを歩みたいという方はぜひ琉球インタラクティブのリクルートを覗いてみて下さい^^*

なぜPaykeに転職したのか

自分のエンジニアとしてスキルやキャリアを高めるために新たな環境に身をおきたいと思い、半年程かけて転職活動を粛々として行っていまして、その間様々なベンチャー企業やスタートアップから声をかけていただきました。

どの会社も非常に優秀なエンジニアが揃っていたりとても魅力的なプロダクトが揃っていたのですが、Paykeを選んだ理由が一番課題や可能性が多くておもしろいと感じたからです。

Paykeのサービスはアプリでバーコードをスキャンすると、その商品情報が多言語で閲覧できるというインバウンド向けサービスなのですが、 メインのユーザーが訪日外国人であるためいつも自分が使うアプリとは違う視点で考えて開発しないといけないことや、 大量のスキャンデータや商品情報を扱うためのデータ分析基盤を作ること、 スキャンして表示する商品情報の数が数百~数千万、または億まで行ったときに出来ることや スキャン時得られる商品情報をよりユーザーに最適化した情報を出せるようにすることなど、 現時点で様々な課題と可能性があり、そこにエンジニアとして挑戦することに強い魅力を感じてJoinすることに決めました。

自分の技術力を高めてプロダクトに反映し、機会があればその経験をシェアしていきたいと思います。 今後ともよろしくお願いします。

オフィスの風景

f:id:arakaji-yuu:20170307193608j:plain

初出社日の満面の笑み

f:id:arakaji-yuu:20170301110039j:plain

受託開発は狩り、自社サービス開発は稲作

昨日ふと思っただけなんですが、受託開発は狩りっぽくて自社サービスは稲作っぽいなと。

受託開発がメインの場合は狩りをしている感覚で、自分の獲物がたくさんいる領域を探したり、大きな獲物を数多く確実に捕らえられるように牙を磨いている。大きな狩りに成功すればしばらくは安泰ですが、しっかり次の獲物を探しておかないといけないので、ずっと研ぎ澄ましている感じ。

自社サービスがメインの場合は稲作している感覚で、実りが出るまでは辛いんだけど実りが出るようになれば安定的に食料にありつけるようになる。ひとつの稲作に成功したらそれである程度食料は確保できるので、今度は違う種類の食材に挑戦したり、より大きく収穫できるように工夫していく。

なんでそんなことを思ったかというと、ただ偶然にYouTubeでレキシっていう人の「狩りから稲作へ」っていう曲を聞いたからなんですが。


狩りから稲作へ

あ、特に結論のようなものはないですよ?

チャットだけが仕事のメインコミュニケーションツールだと問題が出てくるのでプロジェクト管理ツールも使おう。

自分のいまの仕事環境だとメインのコミュニケーションツールにChatWorkを使っています。それ自体は良いことでプロジェクト毎にチャットグループを作ってそこでコミュニケーションを行うことでメールや口頭だけコミュニケーションを取るよりも素早く情報共有ができるし、あとで困ったときに検索することもできるのでとても便利です。

ただ業務上Webの受託開発がメインで、お仕事もおかげ様でたくさん頂けているので普通に10、20のプロジェクトのチャットグループが同時進行で動いています。 それだけのチャットが同時動いているとあまりにも情報過多で、仕事に集中する時間をとることも難しくなってきます。

チャットがメインのコミュニケーションの中で仕事する上で色々問題点が上がってきたのでまとめてました。

コミュニケーションがチャットグループにしか紐付いていない。

チャットだとチャットグループ一つにつきスレッドが一つです。 一つのプロジェクトで一つのチャットグループの場合、そのプロジェクトに関わる様々なタスクに関する議論を一つのスレッドでおこなうことになります。 これにより、特定のことで議論が活発になっているときにはそれが収まるまで他の話をしたい人は待っていたり、逆に割って入ることで議論が追いづらくなります。

タスク管理が貧弱

当たり前ですがチャットはチャットなので、タスク管理機能はついていてもおまけのようなものです。 チャットで仕事を依頼したあとも結局それを管理するためにはエクセルなり、タスク・プロジェクト管理ツールが必要なります。

未読消化するために時間がかかる

仕事上でのタスクの依頼や情報共有、細かいやり取りなどがすべてチャット上に集約されるとものすごい量の投稿数になります。 プロジェクト管理ツールなどでタスクに紐付いたコメントとしてやり取りする場合にはそのタスクに関わる人のみがコメントを読めば済みますが、チャットだとチャットグループに入っている人全員が読むことになります。 その投稿が重要かどうかも読むまでわからないので、結果自分には関係の少ないもの読まなくてはならず、そのために手を止めてしまいます。

一つの解決方法としてBackLogの併用

いま挙げた問題点を解消するために自分がメインで入るプロジェクトでは積極的にBackLogというプロジェクト管理ツールを使い始めました。

コミュニケーションが課題に紐付く

BackLogは各プロジェクトの中に課題というのを登録します。そしてその課題を誰かに依頼したり、議論があればその課題上にコメントすることでコミュニケーションを行います。そのため話が課題に紐付いていることがわかりやすいのでコミュニケーションがやりやすくなります。

タスク管理がしっかりできる

BackLogはプロジェクト管理ツールでベースとなる活動は課題を登録することです。その課題の担当がだれが、期限はいつか、優先度はどれくらいかなどが設定できるのでタスク管理をしっかりチームで行うことができます。まあプロジェクト管理ツールなんで当たり前ですが。

情報が整理されてノイズが減る

タスクの依頼はBackLogで課題を登録して担当者を割り振ることで行います。 課題に関する追加情報や議論があればBackLogの課題上でコメントし、伝えたい人にNotificationを送ることもできます。 プロジェクト全体に関わる情報でストックして見直したい情報、メンテナンスし続ける情報などはBackLogのWIKIにまとめておく事ができます。 それ以外の話や緊急な話のみChatでやり取りするので、情報が自然に整理されてノイズとなる情報がやっていきます。

終わりに

チャットだけだとどんどん未整理に膨らんでいく情報をプロジェクト管理ツールを使うことである程度整理して扱うことができ、結果的に自分の実作業に集中する時間が取りやすくなりました。 いまは自分がメインで入る仕事だけで使っているから上手くいっているだけで、これを全プロジェクトで行うとまた違う問題が出てきそうな気がしますが概ね正しいアプローチだとも思うので、徐々に普及活動もしていこうかなとも思っております。