今回はQiitaの Google Apps Script Advent Calendar 2015 に投稿した 記事 の転載です。
gasifyというツールを作成したので合わせてご紹介します。
require()
したい普段、Node.jsのようなサーバサイドJavaScriptだったり、ブラウザ上のJavaScriptだったりをターゲットにして開発していると、require()
使ってモジュール化してコードを作っていきますよね。
Google Apps Scriptでも同じようなrequire()
使えたらなーと思い試してみたので、その内容を紹介します。
Google Apps Scriptでは、公式に提供されているライブラリがモジュール機能に当たります。ライブラリの機能は ScriptEditor
で読み込みたい別のスクリプトのIDを指定して読み込むことができます(読み込みたいスクリプトに対する閲覧権限が必要です)。
このライブラリ機能は使いたいスクリプトのIDを指定するだけで簡単にコードを再利用できるのですが、ある程度の規模のコードを書くようになると、次のような困った点が出てきます。
さらに、ライブラリの機能ではないのですが、Google Apps Scriptの困った点としてファイルの読み込み順を指定できないという問題があります。機能毎にgsファイルを分割して、それらに依存関係がある場合、gsファイルの読み込み順が重要になってきます。しかし、Google Apps Scriptはgsファイルの読み込み順を指定できないので読み込み順によっては期待した動作をしないという問題が起こります。
そんな時、require()
がネイティブで使えないのってブラウザも同じじゃないか?と思ったので、ブラウザでrequire()
するための Browserify を使えば、Google Apps Scriptでもrequire()
できるかもと思い試してみました。
動作を確認するために次のようなサンプルを用意しました。
main.js:1
2
3
4var hello = require('./hello');
function callHello() {
return hello();
}
hello.js:1
2
3module.exports = function () {
return 'Hello!';
};
main.js
からhello.js
をrequire
して呼び出すだけのシンプルなものです。
これをBrowserifyで1つのjsファイルにしてみます。以下のようにするとmain.js
をエントリーポイントとして依存するjs
ファイルを結合してbundle.js
にまとめてくれます。
1 | $ browserify main.js -o bundle.js |
さて、ScriptEditorを開いてをCode.gs
に上記のコマンドで作成した bundle.js
の内容をコピペして、callHello()
関数を実行してみようとしたのですが、ScriptEditorの関数を選択するコンボボックスにcallHello()
関数が表示されません。
どうも、require()
を実現するためにBrowserifyの関数でラップされてしまっているのでScriptEditorから見えないようです。ScriptEditorから見えないだけで実行はできるんじゃないと思いクライアントサイドのJavaScriptからgoogle.script.run
を使って呼び出してみましたが、callHello()
関数は見つけられず、実行できませんでした。
いろいろ試した結果。グローバルオブジェクトに関数宣言文で関数を定義 しないとScriptEditorからもgoogle.script.run
からも呼び出せないことがわかりました。
以下のようなコードなら大丈夫ということです。
1 | function callHello() { |
困りました、Browserifyで結合したらBrowserify関数でラップされてしまうのでグローバルオブジェクトに関数宣言文で関数を定義できません。しかし、Browserifyを使いながらなんとか関数を定義できないか試して次の条件なら呼び出せることがわかりました。
bundle.js
より前に実行されるコードで関数宣言文を使って関数を定義(中身は空っぽでOK)する。bundle.js
内で上記の関数を上書きする。先ほどの例をこの条件に合うように直してみます。
main.js:1
2
3
4var hello = require('./hello');
global.callHello = function () { // `global`オブジェクトに関数を代入する
return hello();
}
hello.js
は変更ありません。
この内容でbundle.js
を生成します。さらに、生成されたbundle.js
の先頭に以下のコードを追加します。
bundle.js:1
2
3var global = this; // グローバルオジェクトを`global`変数で参照できるようにする
function callHello() { // Google Apps Scriptが呼び出せるように空の関数を定義する
}
このようにすることで、ScriptEditorからもgoogle.script.run
からも呼び出せるようになります。
つまり、bundle.js
を生成したら、
var global = this;
を追加するって、これじゃ面倒くささ倍増です、素直にライブラリ使ったほうがマシです。bundle.js
を生成するたびにそれを編集するなんてやってられません。
少し工夫して追記が必要な内容だけをstub.js
に書いてbundle.js
を生成するコマンドを以下のようにすれば、修正の頻度はビルド毎から呼び出す関数が増える毎に減らすことはできます。
1 | $ browserify main.js | cat - stub.js > bundle.js |
でも、main.js
とかに関数やロジックを追加して、さらにstub.js
にも同じ名前の関数宣言文を追加するのも面倒です。きっと追加するのを忘れて、呼び出せなくて「あぁーー」ってなります。
そこで、gasifyという Browserify のプラグインを作りました。gasify
を使うとGoogle Apps Scriptで動作させるために必要なコードもbundle.js
に出力してくれます。これで呼び出す関数が増えても安心です。もうstub.js
に追記は必要ありません。というかstub.js
自体必要ないです。
gasifyは以下のコマンドを実行してインストールできます。
1 | $ npm install gasify |
使い方はbrowserify
のプラグインとしてgassify
を指定するだけです。オプションなどはありません。
1 | $ browserify main.js -p gasify -o bundle.js |
これで、「あぁーー」とならずに Google Apps Scriptでrequire()
を使えますね
gas-managerという便利なツールがあります。gas-manager
を使えばコマンドでbundle.js
の内容をGASプロジェクトに反映させることができるので、コピペせずにさらに楽になります。
require()
が使える今回はQiitaの Google Apps Script Advent Calendar 2015 に投稿した 記事 の転載です。
gasifyというツールを作成したので合わせてご紹介します。
KAIZENクラウドのランディングページから「事例新聞」のダウンロードができるようになりました。
事例新聞とはKAIZENクラウドのお客様向けのミニ情報誌で、主に福井県内のお客様に配布したり、イベントで配布しています。今回、良い感じに仕上がったので一般公開することにしました。サイズ大きめのPDFなのですが、「KAIZENクラウドって何?」という方は、一度読んでいただけると嬉しいです。
とはいえ、限られた紙面ではすべて説明するのは難しいので、この場を借りてKAIZENクラウドの開発の進め方を補足説明させていただくことにしました。
原則、開発者が、仕様の取りまとめから設計・プログラミング・テスト・運用サポートまですべて担当します。ただし、開発者とは別に「KAIZENエージェント」と呼ばれるお客様対応メンバーがつくこともあります。KAIZENエージェントは、お客様と一緒にどのような改善策が効果的かを考え、整理する責務を負います。今回の事例では、私がKAIZENエージェント兼開発者でしたが、遠隔地のお客様の場合は、例えば東京のKAIZENエージェントと福井の開発者など、別の人間が担当します。
というのも、KAIZENクラウドでは、「お客様となるべく顔を合わせる」ことを重視しているからです。もちろんGoogleハングアウトも活用しますが、よほど遠くない限りはできるだけ会いに行きます。
村中建設様の場合、打ち合わせは概ね以下の内容でした。
効果的だったのは作戦会議だと感じます。現場の方に気持よく使っていただくためには、システムの機能だけでなく、「どのような順番で導入するか」「誰を巻き込んでいくか」など、いわゆる発注者側の立場を理解する必要がありますが、そのような話は、顔を合わせてでないと突っ込めないものであり、そのために毎週顔を出すのです。
このようにお客様との濃密な時間を過ごしながらも、一番時間をかけるのは、やはりプログラミングです。
開発者は打ち合わせで得られたフィードバックを元に、GoogleAppsScript(GAS)でコードを書き、システムを組み上げていきます。このあたりは通常のソフトウェア開発となんら変わるものではありません。
一つ特徴があるとすれば、GASではGmailやカレンダーにSpreadSheetなど、GoogleAppsの豊富なサービスにAPI経由でアクセスできるところにあります。簡単にメールを送信したり、カレンダーに予定を登録したり、シートから値を読み取ったりすることができます。
KAIZENクラウドはお客様の業務効率化を支援する開発サービスですので、これら日常のタスクをシステムに組み込み、自動化できるGASはとても頼りになる開発言語です。
ただし、GASは開発環境が発展途上であり、いろいろと面倒な制約や制限もあります。性能を担保するのも簡単ではありません。レスポンスを上げるためにクライアントサイドのJavaScript(GoogleAppsはWebアプリケーションも開発することができ、jQueryやその他クライアントサイドフレームワークも普通に利用できます)で頑張ったり、Googleの用意したAPI呼び出し回数を減らしたりなど、色々泥臭い工夫をしています。(※これらの工夫については、引き続きこのブログを通じて発信していきます!)
KAIZENクラウドの特徴は、継続的にシステムをアップデートできる「保守モード」なのですが、最初のリリースに盛り込みたい要件はお客様と事前合意(つまりコミット)します。
ただし、出来上がった機能はその都度リリースし、なるべく早くお使いいただけるようにしています。KAIZENクラウドで実現するシステムは、GoogleApps上で動作する比較的シンプルな機能の集まりであり、大規模なシステムテストが不要で、機能単位でリリース可能な場合が多いためです。
ポイントはひとつずつリリースすることです。一度に多くの機能をリリースしようと欲張らず、実際の現場の方に理解が得られるよう、リリースする順番をお客様とご相談させていただきながら、リリースを繰り返します。今回事例に取り上げさせていただいた村中建設様の場合、「一番現場からニーズのある工事実績の検索機能を最初にリリースし、しばらく使ってもらってGoogleAppsになじんでいただく」作戦を取りました。逆に、しばらく使ってもらった結果、「複雑すぎる」との判断で、大幅に機能を削減した機能もあります。
最後に、村中建設様とのお仕事で実感したのは、お客様と仕事を手分けすることの大切さです。
今回のシステムでは、SpreadSheetで既存のExcel帳票を再現し、それらのシートをワークフローするような機能を実現しています。帳票のフォーマットはテンプレート化されているのですが、フォントを大きくしたりといったデザイン変更は、システム担当のお客様に担当いただいております。
これにより、実際の現場の方の要望を、よりスピーディーに組み上げることが可能になりました。システムはあくまでお客様のものであり、一番親しみを持っていただけるのもお客様です。お客様と私達との協力関係で、システムをより良いものに育て上げることができていることを嬉しく思います。
]]>KAIZENクラウドのランディングページから「事例新聞」のダウンロードができるようになりました。
事例新聞とはKAIZENクラウドのお客様向けのミニ情報誌で、主に福井県内のお客様に配布したり、イベントで配布しています。今回、良い感じに仕上がったので一般公開することにしました。サイズ大きめのPDFなのですが、「KAIZENクラウドって何?」という方は、一度読んでいただけると嬉しいです。
とはいえ、限られた紙面ではすべて説明するのは難しいので、この場を借りてKAIZENクラウドの開発の進め方を補足説明させていただくことにしました。
]]>現在、Javaでの開発プロジェクトに参加しています。
Java自体はスマホアプリ開発でも使っていたので馴染みはあるのですが、今回はWebサービスということで、色々と初めてで勝手が分からないことだらけで、チームにフォローしてもらいながら作業を進めています。
今回は、開発中に出会ったBeanマッパーを紹介します。
Beanマッピングとは、ヒトコトで言うと、BeanからBeanへのフィールドコピーです。
こちらの解説が簡潔で分かりやすかったです。
現プロジェクトの担当箇所にて、ある一連の処理で、中間のオブジェクトから出力に使うオブジェクトへ値をコピーする必要があり、「こんなの手で書くもんじゃないだろう」と思って、メンバーに聞いたりググったりしてみました。
まず試してみたのはMapStruct。
リフレクションではなくコード生成するタイプのもので、高速に動作するのがウリ。
ClassA
からClassB
へのマッピングを行う場合、以下のようなinterface
を定義します。
1 | @Mapper |
interface
名および変換メソッド名は自由です。INSTANCE
はマッピングを行う際に利用します。マッピングする方のコードは以下のようになります。
1 | ClassA a = new ClassA(); |
双方同じ名前のフィールド/プロパティ(xxxx
というフィールドに対してsetXxxx()
とgetXxxx()
があるもの)でのコピーであれば、これだけで実現できます。AMapper
の実装を書く必要もありません。素晴らしい。
ところが。
残念ながらMapStructは採用しませんでした。何故かと言うと・・・僕が怠惰だったからです。
ClassA
が以下のようなフィールドを持っていて、
1 | public class ClassA { |
各フィールドに対するsetter
/getter
を書きたくなったのです。
Eclipseで自動生成してくれますが、そういうことじゃないんです。分かりますよね?(笑)
プロジェクトで既に利用されていたLombokを使うと、
1 | @Data |
アノテーション1つで解決です。こうでないと。
で、MapStructはLombokと相性が悪かったのです。LombokはJavaコンパイラに介入してコードを追加したりするのですが、MapStructがコードを生成するのはそれより前であるため、上記のクラス定義のまま、private
フィールドでsetter
がない、という状況なので、エラーになってしまいました。
MapStructを使うために手でsetter
/getter
を書くか、それを避けるためにMapStructを諦めるか。[※]
MapStruct諦めました。
MapStructを諦めて、Orikaを試すことにしました。
“Java Bean mapper”でググると、Dozerというヤツの方が先に出てくるのですが、色々なところで速度比較が行われていて、遅いらしいということが分かったので、そこで比較対象として書かれていたOrikaに決めました。
Orikaでは、ClassA
とClassB
の例のような双方同じ名前のフィールドでのコピーであれば、MapStructのように事前定義が必要なものはありません。
マッピングを行う側では、まずMapperFactory
のインスタンスを取得します。
1 | MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); |
上記は毎回行う必要はなく、シングルトンインスタンスとして保持しておきます。
プロジェクトではSpringを使っているので、DIで対応しました。
マッピングは以下のようにします。
1 | MapperFacade mapper = mapperFactory.getMapperFacade(); |
マッピング元と先が決まっている場合、さらに効率のよいBoundMapperFacade
を利用できます。
1 | BoundMapperFacade<ClassA, ClassB> mapper = mapperFactory.getMapperFacade(ClassA.class, ClassB.class); |
Javaでバリバリ開発してきた方には当たり前は話かも知れないのですが、長年関わってきた組み込み開発ではこれが必要な状況にならず、今まで出会わずに来たので、ちょっと感動。
以上です。
(2015-11-12追記)
※両方を使う例はあるのですが、プロジェクトを分ける必要があります。
現在、Javaでの開発プロジェクトに参加しています。
Java自体はスマホアプリ開発でも使っていたので馴染みはあるのですが、今回はWebサービスということで、色々と初めてで勝手が分からないことだらけで、チームにフォローしてもらいながら作業を進めています。
今回は、開発中に出会ったBeanマッパーを紹介します。
]]>昨日(11/07)開催された 東京Node学園祭2015 に参加してきました。今回は、その時のことをご紹介したいと思います。
東京Node学園祭2015はNode.js日本ユーザーグループ主催のNode.jsのイベントで日本で最大規模のNode.jsカンファレンスです。参会者も400人と多く、海外からの有名ゲストの講演あり、NodeSchoolのワークショップありとイベント目白押しで丸一日本当にNode.jsを勉強して楽しめるイベントでした。因みに、東京Node学園祭は今年で5回目だそうですが、私は初参加でした。
イベントでの講演された方のスライドなどは、今日、明日で多くの方がブログで紹介されると思う[1]ので、このブログでは一つ一つを取り上げて紹介はしないでおきます。個人的にとても面白かったのは @kosamari の Electroknit! という発表です。ネタバレになてしまうので内容はここには書きません。ぜひスライドをみてください。本当に面白い発表です。
学園祭という名前の通りお祭り的な楽しさもあり、初参加の私でも非常に楽しめました。
主催者の方々は参加者同士がコミュニケーションを取りやすいようにと色々工夫されていたようです。懇親会の後に Dan Shaw, Rod Vagg と直接話す機会[2]を作って頂いたり、ひとりで初めてイベントに参加した私でも多くの人たちと話すことができました。
最後ですが、運営の方々、本当にありがとうございます。自分も含めて参加者のみなさんとても楽しんでいたのではないかと思います。また来年も参加したいと思います。いや〜、本当楽しかった。
昨日(11/07)開催された 東京Node学園祭2015 に参加してきました。今回は、その時のことをご紹介したいと思います。
]]>今回は、10月22日に永和システムマネジメント東京支社で Electron のハンズオンを社内イベントとして開催したので、その内容と様子をご紹介したいと思います。
Electron は GitHub がオープンソースで開発しているデスクトップアプリを開発するためのプラットフォームです。Electronを使うとHTML, CSS, JavaScriptなどのWebの技術を利用してデスクトップアプリを開発できます。GitHub の Atom エディタや Microsoft の Visual Studio Code なども Electron をベースに作られています。
Webアプリの開発経験しかないけど、デスクトップアプリの開発をやってみたい人などには、Electronを使ったデスクトップアプリ開発は始めやすいのではないでしょうか。
また、既存のWebサービスをデスクトップアプリとして提供するといった場合にもHTML, CSS, JavaScriptを利用して開発できるので、Webサービスの資産を利用して素早く開発ができると思います。
永和システムマネジメントのアジャイル事業部が開発している idobata というチャットサービスがあります。その idobata の非公式クライアントも Electron ベースです。
では、Electronを題材にしたハンズオンのお話です。ハンズオンは1時間で「Markdownのプレビュー表示とPDF変換ができるElectronアプリ」を作成するという内容です。
ハンズオンにはアジャイル事業部、ITサービス事業部のメンバーが10名以上参加してくれました。
1時間という時間でしたが、参加者のみなさんはElectronで利用するWeb系の技術には慣れているので、初めてでもハンズオンの最後にはアプリを完成させて、動作させるまでできていました。
ハンズオン当日に使用した資料は GitHubのWikiページ で公開しています。資料を読んでけば、一人でも進められるようになっていると思うので、興味が出た人は是非ハンズオンを試してみてください。
ハンズオンで作成したアプリのソースコードもGitHub で公開しているので、アプリを動作だけさせてみたいという人はこちらからチェックアウトして下さい。
Electronのハンズオンを開催した日には、ESM オフラインどう書く というイベントも開催されました。私もそのイベントに参加しましたが。制限時間内には解くことはできませんでした。15分のロスタイムをもらってなんとかNode.jsで解くことができました。こちらも非常に面白いイベントだったので是非挑戦してみてください。ESM オフラインどう書くのイベントの自体はこちらのブログ で紹介されているので一緒にみてもらえるといいと思います。
]]>今回は、10月22日に永和システムマネジメント東京支社で Electron のハンズオンを社内イベントとして開催したので、その内容と様子をご紹介したいと思います。
]]>今回は、私が最近プロジェクトで使用している Spring REST Docs [1]という Java のライブラリを紹介します。
Spring REST Docsを使うと Spring MVC Test で自動生成したスニペットと手書きのドキュメントを組み合わせ RESTfulなサービスのドキュメントを作成できます。
Spring REST Docsを使うと次のようなことができます。
基本は以上です。シンプルです。シンプルですが、Spring MVC Test を実行した結果から生成されるスニペットを利用するので、ソースコードに対する正しい仕様のドキュメントを作成できます[2]。ドキュメントが置いてけぼり….なんてのはよく聞く話です。Spring REST Docs を使えばテストが成功した時だけドキュメントが生成されるので、ドキュメントだけ置いてけぼりというを防げます。
Spring REST Docs のスニペットはAsciidocのファイルとして出力されます。なので、生成された後はAsciidoctorなどのツールをつかってHTMLやPDFなど好みのフォーマットに変換できます。
Spring MVC Test を実行した結果から標準で生成できるスニペットには次のようなものがあります。
curl
コマンドSpring REST Docsは標準のスニペットの生成に Mustache のテンプレートを使っていて、カスタムのテンプレートを指定することで標準のスニペットの出力をカスタマイズすることもできます。
さらにスニペットの生成は Snippet インタフェースを実装すれば任意のスニペットを出力することもできます。
今回は、Spring REST Docs というライブラリとそれで何ができるか、できそうかを紹介しました。
次回は、Spring REST Docs を使って実際にスニペットを出力するまでを紹介したいと思います。
今回は、私が最近プロジェクトで使用している Spring REST Docs [1]という Java のライブラリを紹介します。
Spring REST Docsを使うと Spring MVC Test で自動生成したスニペットと手書きのドキュメントを組み合わせ RESTfulなサービスのドキュメントを作成できます。
今回は、究極のアジャイル同人誌である「Ultimate Agile Stories -Iteration 5」に寄稿させていただいた記事を転載します。記事をまとめるにあたってKAIZENクラウドでの経験も大きかったからです。
私はここ最近、地元福井の中小企業の業務効率化を支援するプロジェクトをいくつか担当しています。今日はいくつかのお客様の事例を題材に、業務効率化プロジェクトにアジャイル開発を適用することの意義について語ります。
ちなみにここでの「業務効率化」プロジェクトの典型は、①帳票メインの事務システム、②リプレイス案件、③低予算で短納期、です。
「利益を生み出すシステムではないので費用はかけられない」&「現場で広く使われている帳票や画面の変更は抵抗が大きい」などといった理由(言い訳)でディフェンシブな開発になりがちで、既存システムを新しいバージョンの技術に置き換えただけの失敗プロジェクトで終わることも多いです。
そうならないよう、もっとも意識するのは「現場の声の収集」です。業務効率化と一言でいってもお客様の思いは様々で、それらを全て受け止めていては収拾がつきません。かといって、我々開発者との窓口となるシステム部門の声だけで進めても、大概は最後に「こんなんじゃない」と言われて四苦八苦することになります。
それを防ぐ意味でも、現場で実際にシステムを利用する現場担当をプロジェクトに巻き込まなくてはいけません。具体的に一番困っている人を紹介いただき、現状の業務ヒアリングをしつつ、以下に挙げるような項目を握っていきます。
業務効率化プロジェクトでリーンキャンバスやインセプションデッキなどの道具を使うことは(めったに)ありませんが、MVP(Minimum Viable Product)に相当するものはあります。
MVPは先ほど挙げた「システムで実現したい具体的な効果とそれを実現しうる機能」・「ここだけは譲れないこと」の中にあります。本当にお客様が欲しいと思う新機能や機能改善をMVPとして抽出し、お客様と合意しましょう。私の場合、現場の方から「これだけで相当お仕事楽になりますね!」と、納得いただけた段階でお見積りをし、ご契約いただいて、プロジェクトを開始します。
やることリストを合意し開発に着手した後は、(開発するシステムの規模にもよりますが)一週間から二週間に一度はデモを実施し、フィードバックをいただきます。これがスクラムでいうところのスプリントなのですが、現場のお客様に密着し開発するプロジェクトの場合は、以下のようなことが発生することがあります。
まず、お客様の担当業務によってプロダクトオーナーが分かれることがあります。お客様によってはIT部門がなく、窓口を一本化することが難しい場合も多いのです。この場合はスプリントごとにフォーカスする業務を分け、バランスよく開発を進めていくと良いでしょう。さもないと、「あちらの担当分ばかり進捗している」などと不安がられ、余計な気を遣う羽目になります。
さらに悩ましいのは「受け入れテストしてくれない問題」です。現場のお客様がスプリントごとに受け入れテストしてくれるので良いフィードバックが早期に得られる。理屈ではそうなのですが、実際は業務が忙しい方が多く、テストを頼んでも実施できていないことがあります。
それで結局、「ごめんなさい。全部できてから最後にまとめてテストします」となりがちなのですが、それだとフィードバックの機会が減り、お互い辛い思いをすることになります。この問題の解決は難しいのですが、私は「スプリントのサイズを小さくする=毎週なんとか時間をとっていただく」、さらに、「確認いただきたいポイントを絞る=アジェンダとなる資料を作りこむ」ことで時間短縮を図っています。デモの場のコントロールをしやすくする策に心を砕きましょう。
これ以外にも、「ごめんなさい!大事なこと伝え忘れていました」問題や、「突然打合せに偉い人が出てきてひっくりかえす問題」などの問題も発生しがちです。
前者は、優先度をお聞きしたうえで後々のスプリントで対応することで納得いただき、後者はプロジェクトバッファを設け、スケジュールに余裕を持たせることで対応します(そんなにうまくいかないことも多いのですが…。現場担当の方としっかりコミュニケーションを取ることで人間関係を把握し、大物には早めに話を通すなどの手立ても必要です)。
また、規模が小さいシステムの開発をお客様に密着して行うと、いわゆる「カウボーイ開発」っぽくなりがちです。お客様の業務に精通してくるほど、トリッキーで属人生の高い 成果物やプロセスが増えるのです。
このような状況はお互いのためになりません。たとえ一人プロジェクトとなってしまってもコードやドキュメントの管理は怠らず、お客様への報告や相談も記録に残せるよう意識してください。
エンドユーザー、さらに現場担当のお客様に密着する開発案件はやりがいが多く楽しいことも多い反面、問題も発生しがちです。
プロジェクトにおける問題で一番苦しいのは「お客様の期待する価値を実現できないこと」ですが、アジャイル開発はこの問題を回避することができる。というより、「この問題を発生させないことを目指して生まれた手法」です。
私は、アジャイル開発はユーザーに価値を届けられる手法として強力だと考えており、今後も、お客様のために試行錯誤しながら活用していきます。
何事も一発でうまくゆくことはありません。アジャイル開発が繰り返しフィードバックを得てゴールに近づいていくように、私たちもより良い開発者になれるよう、試行錯誤を続けていきましょう。
以上
]]>今回は、究極のアジャイル同人誌である「Ultimate Agile Stories -Iteration 5」に寄稿させていただいた記事を転載します。記事をまとめるにあたってKAIZENクラウドでの経験も大きかったからです。
]]>スプレッドシートを使っているとセルには様々な種類の値を入力すると思います。
また、入力した値のフォーマットを指定したりもすると思います。
AppsScriptからも同様にスプレッドシートに色々な値の入力やフォーマットの指定ができます。
今回は、スプレッドシートのセルにフォーマットを設定する方法を紹介します。
AppsScriptでは Range.setNumberFormat(String) 関数でセルにフォーマットを指定できます。フォーマットは文字列で指定します。
この関数はsetNumberFormat
という名前の関数ですが、数値だけでなく日付の値のフォーマットも指定できます。
例えば、次のコードは常に小数点3桁を表示するフォーマットを現在選択しているセルに指定しています。
コードを実行するとセルには1.200
と表示されます。
1 | var range = SpreadsheetApp.getActiveRange(); |
日付の場合は、次のように設定します。
この例では、現在日時を年月日、曜日、時分秒のフォーマット(例えば、2015年8月31日 月曜日 21時58分16秒
)で表示するように指定しています。1
2
3var range = SpreadsheetApp.getActiveRange();
range.setNumberFormat('yyyy年mm月dd日 dddd h時mm分ss秒');
range.setValue(new Date());
このようにセルにフォーマットを指定すれば、利用者に対してより適切な形式で値を表示できるようになります。
フォーマットを明示的に指定しない場合、自動でセルの値から推測されるフォーマットが適用されます。
例えば、文字列として8-30
と入力すると2015/8/30
と日付として値が設定されます。AppsScriptからこのセル値を取得するとString
ではなくDate
のオブジェクトが返ってきます。この振る舞いは次のコードで確認できます。
1 | var range = SpreadsheetApp.getActiveRange(); |
この振る舞いは、セルの値として Date
を期待している場合は問題ありませんが、String
を期待している場合には厄介です。String
を期待して値を設定したにもかかわらず値を取得すると Date
になっているので、セルから取得できる値が String
であることを前提にコーディングしていると期待したように動作しなくなってしまいます。
このような場合、セルにフォーマットを指定することで期待した内容で値が設定されるようにします。
先ほどのコードの 8-31
をそのまま String
として扱いたい場合は @
[1]という文字列をフォーマットとして指定します。8-31
が String
として設定、取得できることは次のコードで確認できます。
1 | var range = SpreadsheetApp.getActiveRange(); |
AppsScriptでスプレッドシートのセルにフォーマットを指定する方法を紹介しました。
Range.setNumberFormat(String) 関数でセルにフォーマットを指定できます。
フォーマットを指定しない場合には自動でフォーマットが適用されるので、必要に応じて明示的にフォーマットを指定するようにしましょう。
@
は入力された値を文字列のまま扱うフォーマットです。これ以外にも指定できるフォーマット文字列はドキュメントエディタヘルプの 数値、日付、通貨の表示形式を設定する で確認できます。スプレッドシートを使っているとセルには様々な種類の値を入力すると思います。
また、入力した値のフォーマットを指定したりもすると思います。
AppsScriptからも同様にスプレッドシートに色々な値の入力やフォーマットの指定ができます。
今回は、スプレッドシートのセルにフォーマットを設定する方法を紹介します。
Google Apps Script はブラウザ上の Script Editor で書いて動作確認ができるので、ブラウザだけあれば開発が始められます。変更履歴の管理もされているので、コードを過去のものに戻したりなんかもできたりします。
でも、gitなどのバージョン管理ツールに慣れている開発者だと、正直これだけじゃつらい、複数人で開発しようとしたときもつらい、とてもつらいです。そこで、今回は Apps Script のソースコードをバージョン管理するために App Script をローカルマシンに取り出す方法の紹介をしたいと思います。
Apps Scriptをバージョン管理ツールで管理するために、どうにかしてテキストファイルとしてコードをローカルマシン上に取り出す必要があります。Apps Scriptはそのあたりもちゃんと用意してくれています。
Google Drive SDKを使ってインポート・エクスポートができます。もちろん、公式ドキュメント にも書かれています。
ただし、インポート・エクスポートできるのは Standalone プロジェクトだけなので注意が必要です。コンテナ(SpreadsheetやDocument)に紐付いているApps Scriptはインポート・エクスポートできません。
公式ドキュメントを見ていただければわかるのですが、インポート・エクスポートは Google Drive の REST API を利用します。なので、特定の言語やツールに依存はしていませんから自分の好きな言語やツールを使ってインポート・エクスポートができます。
でも、インポート・エクスポートしたいだけなので、Google Drive API を直接呼び出すんじゃなくてもう少し簡単に済ませたいですよね。少なくとも私はそうしたい。
そんな(私をはじめとして)簡単に済ませたい人にぴったりのツールがあるんです。これから紹介するツールを使えば自前で Google Drive API を呼び出さなくてもインポート・エクスポートができます。
Google が提供している GWT や GAE を利用して開発するのに便利な Eclipse プラグインです。このプラグインを使うと Apps Script を Eclipse のプロジェクトとしてインポートすることもできます。プラグインの内部では Google Drive API を利用しているので扱えるのはやはり Standalone のプロジェクトだけです。詳しい使い方は 公式ドキュメント に図解入りで説明されています。
Apps Script をインポートするには Eclipse 上で Google アカウントでログインして、インポートしたい Apps Script のプロジェクトを選ぶだけです。Eclipse に慣れた開発者なんかはすぐに使い始められます。
Eclipse のエディタでgsファイルを保存すると、直後に Google Drive 上の Apps Script プロジェクトにも変更が反映されます。使い勝手としては Eclipse 上に Script Editor があるような感じです。
gas-managerは Node.js で動作するコマンドラインツールです。Node.js の環境があれば npm で次のようにインストールできます。1
$ npm install -g gas-manager
インストールすると gas
コマンドが使えるようになります。エクスポートは gas download
、インポートは gas upload
のコマンドを実行すればいいだけです。このツールも Google Drive API を使用しています[1]。
使い始めるにあたって Google Developer Console でクライアントIDを作成して Drive API を有効にする必要があります。Google Plugin for Eclipse に比べると使い始めるまでに少し手間がかかります。でも、Google Plugin for Eclipse にない次のようなメリットもあります。
gas
コマンド-e
オプションで切り替えができます。詳しい使い方は次のページが参考になります。
Apps Script をインポート・エクスポートするツールとして Google Plugin for Eclipse と gas-manager の2つのツールを紹介しました。ローカルマシンにエクスポートまでできてしまえば、あとは git などお好みのバージョン管理ツールを利用して自由にコードの管理ができます。
最近、私は Atom + gas-manager で Apps Script を利用することが多いです。設定ファイルで複数の環境に対してインポート・エクスポートすることができるので、本番環境とテスト環境を使い分けるのにとても便利です。
自分の開発スタイルに合わせてツールを使ってみてはどうでしょうか。
Google Apps Script はブラウザ上の Script Editor で書いて動作確認ができるので、ブラウザだけあれば開発が始められます。変更履歴の管理もされているので、コードを過去のものに戻したりなんかもできたりします。
でも、gitなどのバージョン管理ツールに慣れている開発者だと、正直これだけじゃつらい、複数人で開発しようとしたときもつらい、とてもつらいです。そこで、今回は Apps Script のソースコードをバージョン管理するために App Script をローカルマシンに取り出す方法の紹介をしたいと思います。
2年前から、永和システムマネジメントの仲間たちと「次の事業立ち上げ活動」に従事しています。「次の事業」とは当社サイト に掲げてるところの「esm.succ!」であり、具体的には新しい受託開発サービスを次々立ち上げるのが仕事です。
いろいろと産みの苦しみを味わい、今年に入ってようやく第1弾のサービスである「KAIZENクラウド」を様々なお客様に使っていただける状況にたどり着きました。若干知見やノウハウも溜まってきこともあり、お客様だけでなく世の技術者の方々にも何か貢献したいという思いでこのブログを立ち上げました。技術ネタにとどまらず、いろいろと話題を提供できたらと考えますので、今後ともよろしくお願いします。
少しだけ宣伝しておくと、第1弾サービスのKAIZENクラウドはGoogleApps上にお客様の業務システムを構築する受託開発サービスです。ターゲットのお客様は(実績では)製造・建設・医療系などの中小エンドユーザーで、初期構築用の開発モードと継続開発用の保守モードに契約が分かれます。
ふわふわしがちなやりたいことを整理整頓し、初期構築の範囲で小さく構築・素早くリリース。その後保守開発を継続しながら、お客様の手に馴染む道具としてのシステムに磨き上げてく。そのようなイメージです。システムはすべてお客様のGoogleApps上にリリースし、我々がそれをリモートで保守させていただくため、何かあった場合の対応も素早く行えます。開発者がクラウドを通じてお客様とつながることで、継続的な業務の効率化に貢献できます(だから、「KAIZENクラウド」)。
もうひとつ、「ふわふわしたやりたいこと」を、お客様と一緒に要件に落としこんでいく、KAIZENエージェントというフロント担当によるサポートも特徴です。目指すべき業務についてお客様と語り合うことでシステムの方向性を定め、その後は定期的に開発中のシステムのデモを繰り返すことで、お客様からのフィードバックを開発者に伝えます。
最後にもう一つだけ。
どのようなシステムが向いているかというと、「今までExcelやAccessでなんとか業務を回してきたけど、手入力や紙資料が多く効率が悪い」事務系のシステムは全般的に向いています。ExcelはGoogleSpreadsheetに置き換え、データの共有と業務の自動化を実現します(SpreadsheetはExcelになれたお客様にとって敷居が低い入力ツールです)。
CalendarやSiteと連携した仕組みも得意ですし、クライアントサイドのJavaScriptをフル活用する、いまどきのWebアプリも手軽に構築できます。
…すいません。話が長くなりそうなので、具体的な事例はまたの機会に。
私はいくつかのお客様にとってのKAIZENエージェントなのですが、同時にGoogle Apps Script(GAS)でコードを書く開発者です。GASはサーバーサイドで動くJavaScript+Googleが提供する高レベルなAPI環境です。高レベル故向き不向きがあるので、便利さを実感したり苦労したりの毎日ですが、概ね私たちは気に入っていて、ブログのサブタイトルにも登場させています。
「GoogleAppsScriptでハッピーワークライフ」というサブタイトルには、GASによってスピーディーに業務の効率化を支援することでお客様をハッピーしたいという思いはもちろん、おもしろい技術に関われる開発者にとってのハッピーさも追求したいという思いを込めました。
KAIZENクラウドは中小のエンドユーザーを対象としており、費用をかけずにお客様の手になじむ業務システムを素早くサービスインすることにフォーカスしています。
なので、やることも絞っています。不特定多数がアクセスするようなシステムには提案しませんし、基幹システムを構築する用途にはお勧めしません。帳票はOKですが、既存のExcel・Word帳票フォーマットの流用を優先します。一から帳票設計するようなケースはほとんどありません。独自のユーザー認証ではなくGoogleの認証を使っていただきます。
(Googleが狙ってる領域なので当たり前なのですが)、このような「AccessやExcelでやってきた部門情報系システム」の構築にGASはマッチします。Goolgeが提供するAPIは強力で、SpreadsheetやDocumentをGASから簡単に扱えます。既存のExcelを自動でSpreadsheetに変換し、それをデータベースのように利用するkintoneのようなアプローチも大得意です。
さて、このようにGoogleに乗っかった開発をしていると、心地よさと同時にロックインされているような不安を感じるかもしれません。私個人としては「全体としてはクローズだけど、そこに採用されている個々の技術はオープンだからいいか」ぐらいの割り切りです。GoogleのAPIは覚える必要がありますが、JavaScriptやHTMLの知識と経験は活かせますし、今後別のプラットフォームで開発をすることになっても役に立つでしょう。(GoogleのAPI廃止のまつわる苦労話は、また別の機会に書きます)
ちなみに、「今どきのエコシステムを利用したAppsScript開発に取り組んでいる」仲間もいます。その取組もこのブログに書いてもらう予定なので、そちらもご期待ください。
最後にすこし自分の話を。
現場を継続し、評価をいただき、新しい引き合いをやご指名をいただきながらも、点から面に広げていくのが受託開発ビジネスのセオリーです。キャリアを積んだ受託開発SEの方なら、このセオリーに基づき、会社から「営業的な動き」を期待されることがあるかと思います。私もそうでした。お客様の信頼をいただき仕事を広げたり、それに必要な見積りや交渉ごとにも参加するようになってくる。こうやって、いつの間にか「営業もする開発者」にちょっとだけジョブチェンジしたつもりでした。
でも、社内とはいえ事業を起こす立場になってみると、やっぱ、営業の仕方が全然違うことに気が付かされます。ゼロ状態からから顧客を見つけていくことの難しさよ。そうやって、苦労してつながったお客様に対しては、なんとか期待に応えたい気持ちの高まることよ。うらはらに事業として成り立つ採算性を確保する苦労。そして、お客様に正確かつスピーディーに応えるには、自分が開発できるぐらいの技術をキープしてないとダメだというずっしりとした実感。
このような経験から、自分は今、「開発もする営業」を目指しています。
ちなみに私、KAIZENクラウドに限らず新規サービスの企画・マーケティング担当でもあります。そのあたりの話題も、おいおい書いていく予定なのでよろしくお願いいたします。