2016.03.18

高品質なアウトプットを出す事が出来たケース紹介 -ベトナムオフショア開発-


こんにちは。次世代システム研究室のT.Kです。
2016年もアッという間に3月になり、憂鬱な花粉の季節になってしまいました。
次世代システム研究室と関わりの深いベトナムには花粉症が無いそうで、この時期は一番羨ましいと感じている今日この頃です。

今回は昨年より関わっている社内開発案件の対応において、数点問題は発生しましたが他案件に比べ、日本側の発注コストが低く、ベトナムからのアウトプットがほぼ期待通りの成果を出す事が出来たケースがありましたので、そのお話をしたいと思います。

1. 要件概要


対応の概要としては、『1日1回バッチで、データベースの情報をSpreadsheetへアップする』と言う事が今回の目的になります。
現在、私が関わっているプロジェクトでは開発拠点がクライアント側開発チーム+企画・運営チームとサーバー側開発チームの2拠点に別れており、企画側が生データを任意に確認しづらい状況にありました。
主要な数値をまとめたKPIツールは用意していましたが、企画側視点で自由にデータを集計したい事と、企画側がSpreadsheetを利用したいと言う事から発生しました。
拠点イメージ

私自身、業務で積極的に”Spreadsheet”を利用していなかった事と、今回の様な案件はベトナム側に依頼しやすくアウトプットの精度にも期待できると思い、Spreadsheetの仕様調査から開始しました。

2. Spreadsheetの仕様調査

    調査依頼

    今回の要件は比較的シンプルであり、必要なドキュメント類もネット上に多く存在するので、仕様調査からベトナムメンバーにお願いする事にしました。
    私の方から調査を依頼した内容をまとめると下記になります。
    		1. 基本的な"Google SpreadSheet API"の使い方
    		  ・fuelPHPからの利用方法
    		2. 使用制限の確認
    		  ・API呼出制限数
    		  ・1ファイルの限界行数
    		  ・1ファイルの限界シート数
    		  ・1シートの限界行数
    		3. アップロードデータを一括で送信する事は可能か
    	

    今回ベトナム側に依頼しやすいと考えた理由は下記3点がありました。
    		1. Spreadsheetの仕様は公式サイトに記述されている。
    		  日本側から細かく伝える必要が無い。
    		2. 開発環境の設定などは特に無く、想定通り動けば良い
    		  実際の挙動がベトナム側で確認できる
    		3. INとOUTがハッキリしていて、詳細な処理部分に仕様が無い。
    		  マルっとベトナムメンバーに任せられる
    	
    今までの経験上、上記の様な状況で実装上に細かな制約が無い案件(ブラックボックス案件!)に対するパフォーマンスとアウトプットは期待出来る傾向にあると感じています。
    ※最終的に受入時にはソースの確認は行いますが。。。

    調査結果

    ベトナムメンバーには、他の作業と平行して調査を行ってもらい、2日程で調査報告を貰いました。
    報告をもらった時に自分で確認しなかった事が後ほどの反省点になりますが、この時点では報告内容を元に開発仕様を作成しました。
    【注意】結論から言うと下記の制限は数年前のもので、現在の仕様とは異なるものでした。

    メンバーからの調査結果と現在の仕様を下記にまとめます。
    調査結果の仕様は5年ほど前のもので且つ、一部誤りがある調査結果でした。
    		調査結果
    		  ・サンプルソース実装完了
    		  ・1シートの限界行数は、行数では無くカラム数に依存し、1シート40万セルまで
    		  ・1ファイルの限界シート数は200
    		  ・ファイルは一括でアップロード可能
    		   ⇒API呼出制限は不明
    		現在のGoogleドライブの制限仕様
    		  ・ドキュメント:半角 102 万文字
    		  ・スプレッドシート:200 万セルまで
    		  ・プレゼンテーション:100 MB
    		  ・その他ファイル:5 TB
    	
    ※参照サイト:https://support.google.com/drive/answer/37603?hl=ja

3. 開発実装

    この時点では調査結果から、1シートに40万セル出力可能、1ファイルに200シートまで出力可能であれば、毎日1ファイルで対応できると判断し、開発を開始しました。

    今回の仕様はシンプルですので、下記一文に少し条件を追加してベトナムメンバーに対応を依頼しました。
    		Spreadsheetへテーブル情報を出力するバッチの作成をお願いします。
    		  ・毎日出力するファイル名は『YYYYMMDD_○○○○』
    		  ・TBL毎にシートを分割し、シート名をTBL名にする
    		  ・各シートの1行目は物理名を記載する
    		  ・登録は一括でアップロードで行う
    	

    開発作業も並行作業で進めてもらいましたが、3日程で完了報告を貰う事が出来ました。
    自分のローカル環境で動作確認を行う為、メンバーから共有された下記手順を実施。
    		php composer.phar self-update
    		php composer.phar update
    		sudo yum install zip
    	
    更新されたファイルを確認すると既存の”composer.json”に”google/apiclient”が1行追加されていたので、その為のアップデートのようです。
    zipの方は一括送信用ですね。

    ローカルで準備を整えバッチを実行し、意気揚々と指定アカウントで”Spreadsheet”を確認したところ、しっかりとTBL毎にシートが作られている!!
    この時点では『完璧だ!!素晴らしい!!”』とテンションMAXだったのですが、シートを見るとテーブル定義しか無い。
    どこかにデータがあるのかと探して見ても無い。一旦落ち着いて、依頼仕様を確認…
    ・・・
    ・・・・・・
    ・・・・・・・・・まさか『テーブル情報 => テーブル定義』!?
    更に冷静に世の中の認識を確認する為、google先生に尋ねてみました。
    google
    “おぉう google お前もか!!”

    少しだけ『”毎日バッチでテーブル定義出力する事はおかしい”と考えて欲しかった』と思いましたが、これは私の問題でしたので、理由を説明した上で修正対応を依頼しました。

    その後、修正対応中に前述の”調査ミス”が発覚しましたが、『制限を超える場合のみファイルを分割する』対応で問題を回避する事が出来ました。
    Spreadsheet_nyanko_B


    下記に対応内容のポイントをまとめました。
    アップロード先Spreadsheet準備 サーバ
    • 1. “composer.json”の修正
    • 			"require": {
      				"php": ">=5.3.3",
      				"composer/installers": "~1.0",
      				"fuel/docs": "1.7.2",
      				"fuel/core": "1.7.2",
      				"fuel/auth": "1.7.2",
      				"fuel/email": "1.7.2",
      				"fuel/oil": "1.7.2",
      				"fuel/orm": "1.7.2",
      				"fuel/parser": "1.7.2",
      				"fuelphp/upload": "2.0.1",
      				"monolog/monolog": "1.5.*",
      				"michelf/php-markdown": "1.4.0",
      				// 追加
      				"google/apiclient":"*"
      			}
      			
    • 2. Spreadsheetアクセス用の”access_token”等の情報を保持
    • 3. バッチ本体
    • 公開情報をベースに、アップロードファイルを圧縮する処理を加えました。
      			// Get the API client and construct the service object.
      			$client  = $this->getClient();
      			$service = new \Google_Service_Script($client);
      			$scriptId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
      			・
      			・
      			アップロード情報をzipにまとめる処理
      			・
      			・
      			// ファイルをアップ(※ファイル内容展開処理はdrive側に実装)
      			$request->setFunction('createSheetContent');
      			$request->setParameters($json_file_name . ".zip");
      			$service->scripts->run($scriptId, $request);
      			
      			// 処理の終わった不要ファイルを削除(※削除処理はdrive側に実装)
      			$request->setFunction('removeAllZipFile');
      			$request->setParameters('.zip');
      			$service->scripts->run($scriptId, $request);
      		
    google drive
    		アップファイル展開処理を追加
    		 ⇒サーバ側の"setFunction"で指定している処理本体
    		  createSheetContent
    		  importFromCSV
    		  removeAllZipFile
    		  等
    	

4. 反省

    課題点としては、仕様調査ミスと仕様伝達ミスの2点になります。
    仕様調査ミスは致命的な状況に繋がる事も有りえたと反省する出来事でしたが、幸い仕様変更で回避でき、今後の改善事項として再発防止に努めます。

    仕様伝達ミスに関しては、日本語が母国語では無いメンバーに伝えている事を念頭に文面の見直しを徹底する事にしました。

5. 総括

    今回のケースでは、日本側が掛けた時間とベトナムからのアウトプットを比較すると今回は上々のアウトプットが出たと感じています。

    全員ではありませんが、比較的『日本側の仕様は正しい。』と考えがちなメンバーが多いと感じています。
    ベトナムメンバーには仕様を忠実に守るのでは無く”疑問”を持ってもらう事で、仕様ミスがあったり、曖昧な仕様であっても、精度の高いアウトプットを出してもらえるのではと考えています。

    ベトナムメンバーの成長に更に期待する事も多くありますが、着実に成長して来てくれていると感じる今日この頃です。

次世代システム研究室では、アジャイル開発の導入やオフショア開発を一緒に推進してくれる方を募集しています。アジャイル開発、オフショア開発経験者の方、経験は無いけれどぜひやってみたいという意欲のある方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いいたします。

エントリー(募集一覧)


皆様からのたくさんのご応募、お待ちしてます!