続・Excelで作ったツールを業務運用にのせる場合に考えておくべきこと
前日の続きです。
こういう考えに基づいて、メリットとデメリットを勘案した上で、Excelツールを作って運用にあげたとします。
そうすると得てして起こりがちなのが、
勘案した上で気にしない事にしたデメリットの存在をすっかり忘れてしまう
ということです。
特に、ツールが顧客の手元で運用されており、自分らがそのツールの提供元である場合、この【健忘】こそが我々の真の敵になるのであります。
検討段階でこんな会話がなされたとします。登場人物はベタな感じの
A:SE
B:営業
C:プログラマ
てなイメージで書いてます。
A:「この機能をシステムに追加するとなると工数がかかるから、Excelでマクロ組んで簡単な帳票にしてあげて、それで代替してもらおうか。」
B:「それだと工数そんなかかんないの?」
C:「大筋はOKなんすが、○○部分の仕様だけは、ちょっと面倒ですぜ。ExcelVBAでチマチマ実装しなきゃなんないんで手間がかかるし、その後のメンテが辛そうすね。それがなきゃサクっといけますが。」
A:「○○部分の仕様って、△△部の人だけが必要なんでしょ?だったらそのツールを部署限定にしたらいいよ。その面倒な仕様の部分は××部の範疇だからね」
B:「工数そんなかかんないならいいね。」
お客:「部署限定ね。おっけーその方向でいいよー。」
C:「その仕様ないんだったら超ラクっすね。やったー。」
誰も傷ついていません。みんなが、この案のメリットとデメリットを認識し検討した上で合意し、誰もが納得のいく結論を得る事ができました。めでたしめでたし・・・しかし、ここで健忘してはいけないことがあります。それは、
今回すんなりいったのは、とあるデメリットを「気にしない事にする」という決断があったからこそである
ということです。
上のA,Bとお客さんには、Excelツールにすることで工数を減らせた、という成功体験が残ります。しかし、「Excelでツール作る」と「工数が軽く済んだ」の2つは、直接結びついてはいません。Excelで実装しようとすると色々と苦労しそうな仕様は盛り込まないことにしたから工数が軽く済んだのであり、身もフタもない言い方をすると
Excelで工数が軽くなるように作った
というだけのことです。これじゃなんなので少し真面目に言い直すと
何を優先させるべきかの軸が全員で共有できており、その軸に沿ってデメリット側を調整することができた
のが勝因です。
先ほどのツールがしばらく運用された後、そのツールに対して、ぜんぜん違う仕様要求が来たとします。このとき、BやAの頭に「部署限定の話じゃないから大丈夫だろ」とか「もし工数かかるようなら工期を長めにもらえばいいや」というバクゼンとした思い込みがあると・・・ものすごく軽い気持ちでやりまっせーと約束しちゃったりします。前回はちゃんと行っていた、「デメリットとメリットの調整」をすることなしに。
そうするともう、Cの一人負けとなります。
実装自体が大変かもしれないし、実装はなんとかなってもリリースが大変かもしれない、運用が煩雑になって問い合わせが急増するかもしれない...さらに、これら問題を回避する策は存在するけど、それをやってしまうと、さらに次の仕様変更に対する耐性が損なわれるかもしれない...いろんなデメリットが考えられるはずなのに、検討したつもりになっていたとしたら、これは泣けます。
Cの一人負けというのは、結局、回り回ってユーザの不利益にもつながります。出来上がったものが残念な仕上がりになっているわけですから。Cが2、3日徹夜すりゃ解決する話ならいいですけど、エンジニアが2、3日徹夜したら、ユーザは半年とか1年ぐらいは困ることになると思っといた方がいいです。断言。
大変だからやりたくない!そんな仕事取ってくんな!とか言ってるわけではなく、すべては準備とか心構えとかの問題です。
それらは、プロジェクトの初回にはみんな気をつけてやるんですが、いったん喉元過ぎたら忘れられがちなものです。リリース後も継続して心構えをしておく、前に議論していったんの結論が出たことでも、常に忘れずに意識の俎上に載せる、ということがとても重要です。
実現したい仕様によって、工数はかわる、利便性もかわる。仕様の実現レベル感もかわります。システム屋なら誰でも知ってる当たり前の事なんですが、ことExcelでの開発に関しては、その大と小の振れ幅というか、
Excelをフロントエンドにすることによるメリット(と思われているもの)を享受するために支払う『犠牲』のようなものは、想像よりもかなり大きい
ように思います。それは前回に記載したようなExcelによる開発ならではの特性から来ています。そしてまた、
Excelによる開発においては、大のほうの見積もりが甘くなったり、支払われる『犠牲』を過小評価する傾向がある
というように思います。
この車幅感覚のようなものを、少なくとも自分と一緒に仕事してる人たちにはわかっといてほしいと切に願う次第です。
Excelで作ったツールを業務運用にのせる場合に考えておくべきこと
いつもと少し毛色の違った話題。
システム屋をやっていると、Excelに数式やVBAマクロを埋め込んだツールを作り込むことがよくあります。自分やチーム用の便利ツールとして作るときもあれば、構築したシステムの補助輪的役割をもつものであったり、逆に業務の主役級の役割をもつものとして作ることもありますね。
ツールの作りの複雑さも様々で、業務における主流か傍流かと、そのツールが複雑か単純かには相関関係がなかったりします。
そのような、我々にとって身近なExcelツールですが、実装する立場の人にはお判りの通り、開発ツールとしてはいろいろな制約なりやりにくさがあるものです。そういうやりにくさをどう解消したらいいのか、技術的な側面から検討を進めている人たちがいます。
しかしながら一方、技術をこねるよりも手前の段階で考えておかなければならないことって、たくさんあるよなあ、というのが今回のお話です。
Excelツールを業務運用にのせるにあたり、次のようなことをどうクリアするのか、が問題になってくると思ってます。
- Excelバージョン違いをどのように吸収するか
- VBA開発時、共通モジュールをどうやって本当に共通のものとするか
- 改修バージョンを実運用環境にリリースするときに発生する諸問題
- 実運用環境のセキュリティ的縛りに対する対応
- ユーザによる改変への対応
これらを考慮に入れた上で、あえてExcelを選ぶのどうなの、選ぶならどう作るの、ということです。
順にコメントします。
1. Excelバージョン違いをどのように吸収するか
これへの解の1つはバージョンを固定してしまうことだと思いますが、未来永劫そのバージョンを使えるとは限らないので、結局いつか困る。そもそも、Excel本体がある程度の下位互換性に対応してしまっている以上、細かいところで困る局面は多々あります。
Excel本体だけでなく、参照設定してる外側のバージョン違いでも困ります。
2. VBA開発時、共通モジュールをどうやって本当に共通のものとするか
ちょっとわかりづらいかもしれませんが、よくある話として、Common.bas みたいなモジュールを作って共通モジュールをそこに突っ込む的なことをしたり、環境ごとの差異を、Config設定用シートを用意して実装外から与えるようにすることが多いわけですが、同時に二人以上で開発しようと思ったら結構破綻しがちですよね、という話です。
ファイル単位でしかバージョン管理ができない件も根っこは同じかと。
3. 改修バージョンを実運用環境にリリースするときに発生する諸問題
実行環境にリリースする際に、Excelファイルごと上書きが可能な仕組みにしておかないと、絶対に成り立たない。
前述のConfig用のシートを持つとか、実行履歴や処理結果を同一ブックの別シートに持っちゃう、などしてしまうと破綻します。
4. 実運用環境のセキュリティ的縛りに対する対応
一例をあげると、実行環境がマクロ有効ブックをNGにしている場合とか(時々「マクロ警告すら出させたくない」とか言う人がいたりして(論外?))。また、データ可視権限の問題とか。
そんなのに対応するくらいならAccessで作ろうず、などの話になります。
5. ユーザによる改変への対応
故意のものとうっかり系のものとがあります。故意のものは、ユーザが詳しい人で、自分用に数式を埋め込んだりするケース。うっかり系のものは、消してほしくないセルの数式を消してしまうとか、行挿入されてしまうと困るようなコーディングになっているとかです。
これは、セルの保護とかで丁寧に実装してあげればある程度は防げますが、工数軽くしたいからExcelにしよう的なところから出発してるときは、確実にボディーにくる。
ごちゃごちゃ書きましたが、Excelを【フロントエンド】としたいならば、
- xlsmファイルを、いつなんどき、まるごと上書きされようが、平気な作りにする
- 使う人がExcelに精通してない(逆にね!)
- もしくは、これらの「困る」を「別に困りませんけど?」に意識転換できるポジティブ思考
といったところを満たさない限り、選んではいけない、ぐらいのところまで思っています。
直接的には1点めが最重要ポイントですが、それをクリアするだけでも、改修版リリース時に面倒が発生する、もしくは、その面倒さを吸収するための仕組みを何らかの方法で作り込む、などという悩ましい状態になりがちで、となると、逆に3が真の最重要ポイントになります。3が満たされりゃ1を考える必要ないんで:#)
実は【フロントエンド】にするのが目的じゃなかったんじゃない?出力閲覧系だけExcelになってればよかったんじゃない?という真の目的の検討にもつながるのかなーと思います。
実は、こういう検討をすれば解決・・・ではありません。これらをちゃんと考慮して運用にのせた後にも問題は横たわっています。
次回へつづく!
Google Cloud SDK を完全にアンインストールする方法
GAELauncherによるupdateでは、/usr/local/bin および /usr/local 配下にシンボリックリンクが作成される。
gcloudでupdateすると、それは作成されない。
Cloud SDK を完全にアンインストールするには、次のようにしたらいいんじゃないかと思う。
# The next line updates PATH for the Google Cloud SDK. source '/Users/<your_name>/google-cloud-sdk/path.bash.inc' # The next line enables bash completion for gcloud. source '/Users/<your_name>/google-cloud-sdk/completion.bash.inc'
sudo find -L /usr/local/bin -type l -exec rm -- {} + sudo rm /usr/local/google_appengine
たぶんこれで消えたはず。。。
【未解決】CloudSDKをアップデートしたら、PATHが最新のディレクトリにならない→対処療法あり
いつからそうなったのか、きっかけがわからないし、未だに解決していないのだが、起こったこと時系列でメモしてみる。
- OAuth の検証をしようと思い、とあるサンプルコードをダウンロードして、ローカル開発サーバで実行してみた。
- 認証処理の途中で、from ndb import なんたら の箇所でエラー。ndbというパッケージが見つからないといっている。
- エラーになっている箇所は、サンプルコード内ではなく、サンプルコードから呼ばれたauthモジュールの中だった。
- その箇所をみてみると、from google.appengine.ext.ndb … とするべきなのに、してない。そりゃみつからない。
- 最新版のバグなのかな?と思って調べると、Issueがあった。もう直っていて(https://code.google.com/p/webapp-improved/issues/detail?id=33&can=1&q=auth%20ndb)、最新版には反映されている(https://code.google.com/p/googleappengine/issues/detail?id=6279)という。
- webapp2.5.1には同梱されてると書いてあるので、自分の環境のgoogle-cloud-sdk配下を見てみると、果たして、webapp2.5.2がダウンロードされているではないか。
- それなのに何故そんなエラーが?と思い、PYTHONPATHを確認してみることに。
- 適当なサンプルコードの中で、"sys.path()"の中身を出力させてみると、バグが入り込んでるバージョン2.3にPATHが通っている!
- なんでだよーと思いつつ、SDKを最新版にアップデートしたときに、PATHの書き換えをするか?とプロンプトされた際に、間違えてNを選んでしまったのかな?と疑う。
- .bash_profileをチェック。
- その中で呼ばれてる、path.bash.inc と completion.bash.inc をチェックするも、知識不足で意味がわからない。
- google cloud SDKの再インストールを試みるも、解決せず。
- google cloud SDKを別ディレクトリにインストールしてみるも、解決せず。
- 新しいユーザを作り、1から開発環境をインストールしてみたら、パスが最新に通った。
- うまくいった環境との違いがわからない。
- 惨めな気持ちになりながら、現ユーザから新ユーザに開発環境を移す。
これは関係あるのかしら??
http://code.google.com/p/google-cloud-sdk/issues/detail?id=26
続報
上記リンクは関係大有りのようだ。
そして、WontFixで閉じられている。むう。
こういうの見つけた。
https://code.google.com/p/google-cloud-sdk/issues/detail?id=72
gcloud経由でupdateしたときと、GAELauncherのGUIからupdateしたときで、シンボリックリンクの張り方が異なる、という話なんだろうか。
そうであれば心当たりがある…今まではGUIからupdateしていたが、直近のupdateはgloudのコマンドから行ったのだ。
今のところの結論としては、updateするならやり方を変えるな。ということか。
続・続報
今回バージョンが最新にリンクされてないのは、webapp2なのだが、これは、gcloud経由でupdateしたか、GAELauncher経由でupdateしたかには関係なかったようだ。
app.yamlに
libraries: - name: webapp2 version: "2.5.2"
の記述が無いと、いずれの方法でupdateしてあっても、webapp2.3にPATHが通っていた。
loggingのログレベルの指定方法
過去記事
http://d.hatena.ne.jp/noazoh/20140731/1406783304
の補足。
開発サーバのログレベルはアプリケーションごとに設定することができる。Google App Engine Launcherにて、プロジェクトのApplication Settings で、起動時フラグを設定してやることによって可能。
ところで、そのログレベル関連のパラメータには
--log_level={debug, info, warning, critical, error} --dev_appserver_log_level={debug, info, warning, critical, error}
と2つあるのだが、その違いは、
前者は、アプリケーション(我々が開発するコード)から出力されるloggingに対する指示、後者は、開発サーバから出力されるlogging(システムログ的な)に対する指示である。
なので、よほどのことが無ければ、--dev_appserver_log_levelを指定することはないだろう。
いずれの場合も初期値はinfoである。
HTTPリクエストのメッセージ長の制限は?
HTTP GETおよびPOSTのリクエストメッセージにサイズ制限はあるのか?
調べ中。
GETメッセージ2047byte説がある。2009年の記事。
http://d.hatena.ne.jp/Kazumi007/20090921/1253501500
POSTメッセージ10MByte説がある。2011年の記事。
http://php6.jp/python/2011/01/14/post_limit_10mb/
同じく2011年の記事、reqeust/responseともに10MByteまで説。
http://it-trick-java.appspot.com/gae/c17001/page16055.html
リストを逆順に並べ替えるreverse()メソッドには戻り値がない
リストを逆順に並べ替えるにはいくつか方法があるが、そのうちの
リストオブジェクト.reverse()
であるが、これって、逆順に並べ替えた結果を返すfunctionなのではなく、リストオブジェクトの中身を実際に並べ替えてしまうmethodなんですね。
つまり、こういう↓使い方をするもの。
list = ["a", "b", "c"] list.reverse() print list #["c", "b", "a"]
こういう↓使い方をするものではない。
list = ["a","b","c"] reversed_list = list.reverse() print reversed_list #None