RPAツール随想:どうせ勝てる見込みの無い戦場へ送り込まれるとしても、一番強い武器をくれ
Disclaimer:この文章は私の個人的な考えであり、職業人としての私の考えとは異なります。私に仕事を恵んでくれる場合は、それがいかなる内容であっても、与えられた環境と個人の能力の制限内で出来ることを精一杯いたします(だから仕事ください)。
この記事はナントカRPAアドベントカレンダーのX日の記事です(重言)。
RPAって流行ってるんですか?
こちらの記事もなかなか興味深い。作業時間が減っても長期的には数十人程度の人員削減にしかならないと:
まずはおさらい
コンピューターの最も効果的な使い方は、従来は手作業で行っていた事務などを代わりに自動的に行ってくれることだ。Computerは日本語では電子計算機である為、まずは銀行などがまっさきに飛びついて、今まで銀行員が手作業で行っていたお金の計算を肩代わりさせた。そして大企業なども、基幹システムと呼ばれるような会社運営のコアを任せるようになった。何しろコンピューターときたら、深夜だろうと休日だろうと文句一つ言わずに働いてくれるのだから、こんなに頼もしいことはない(それのお守りをさせられる人間は別だけど)。基本的にコンピューターは、オペレーターと呼ばれる専門の担当者が操作するものであり、事務作業者が操作するようなものではなかった。オペレーターは、コンピュータールームという神殿に仕える巫女であり、信者は何やら紙を持ってその巫女に渡すと、巫女は何事かの神事を執り行った後、神からのお告げが紙になって戻ってくるのだ。
と、これが日本だと1980年代くらいまでの話。
1990年代になると、コンピューターの小型化、高性能化、低廉化が一気に押し寄せて、冷蔵庫のような汎用機は袖机くらいのミニコンになり、机上のワークステーションになり、Sunのワークステーションが55万円で安い!と話題になろうが、それよりはるかに安いパーソナルコンピュータ(PC)によって絶滅した。そして今までは神殿にしか鎮座していなかった神が、事務員一人ひとりの机の上に置かれるようになった。それまでの神との対話は、限られた巫女にしか出来なかったのだけど、今はGUIとマウスという新しい神器により、誰でも神と対話することが可能になった。
しかしここで古の神事は忘れ去られた。コンピューターとは、複数の事務作業を横断的に行う、事務作業プロセスの<つなぎ>の部分も含めて自動化するものであるということを。Excelが自動で計算をしてくれれば、それは自動化にはなるだろうが、その計算結果を、例えば報告書だとか決算書だとか、最終的な出力先に持っていく作業は相変わらず人間がフロッピーディスクやUSBメモリに入れて担当者へ渡していた。ここで古代の便利さは失われた。乾燥機能付き全自動洗濯機だったものが、洗濯のみの洗濯機になったおかげで、人間が物干し竿に洗濯物を干す必要が出たのだ。
1980年代からPC向けローカルGUIアプリであっても、モノによってはアプリ内で自動化できるスクリプト言語を実装している場合があった。Excelで言うとVBAがそれだ。1990年代になると、GUI OSのアプリ内のみならず、複数アプリ間を繋げるスクリプト言語も登場したので、今で言うRPAのようなものは実現可能だった。Classic Mac OSでいうAppleScriptがそれだ。しかし当時、そのようなものに興味を持つのは非常に退屈なルーチンワークを自動化したいと願っていた印刷所くらいなもので、一般には普及しなかった。それにプログラマーたるもの、英語に近い構文なので(ネイティブには)覚えやすいという触れ込みのAppleScriptなぞ、冗長で嫌いだったのだ。
当時Windowsはどうしたって?Windows内のCLIであるコマンドプロンプトに、UNIXに比べてとても非力なバッチスクリプトを書いてしのいでいた。便利さは1980年代のMS-DOSから何ら変わることはなかった。
当時より退化したと言わざるを得ない部分もある。Excelファイルはバイナリ形式で保存されるため、基本的にExcelファイルを理解できるのはExcelアプリのみであり、これを更に外部ツールで加工するといったことが難しい。
Mac OSやWindowsといった、パーソナルコンピュータ用OSとは別に、UNIXというOSもある。Mac OS X(現macOS)以降もiOSもAndroidも、要はWindows以外はUNIX一族だと思ってよいけど、UNIXには登場以来の思想があった;データは全てファイルであり、アプリケーションは単機能だけを持ち、それらを組み合わせて一つの仕事をするSoftware Toolsという考え方がある、というものだ。古代神殿で行っていた事と同じでしょう?
具体的に言えば、こんなフォルダの中身があったとする。いくつかファイルがあるけど、その中で特定の文字列を検索したい。
hiroki % ls -la
drwxr-xr-x 6 hiroki staff 192 1 4 2019 .
drwxr-xr-x 19 hiroki staff 608 1 4 2019 ..
-rw-r--r-- 1 hiroki staff 810 1 4 2019 App.vue
drwxr-xr-x 3 hiroki staff 96 1 4 2019 assets
drwxr-xr-x 4 hiroki staff 128 1 4 2019 components
-rw-r--r-- 1 hiroki staff 320 1 4 2019 main.js
ここで find . -name "*" | xargs grep geonames
と入力して、文字列geonamesと書かれたファイルを検索する。
hiroki % find . -name "*" | xargs grep geonames
grep: .: Is a directory
./App.vue: var that = this$.getJSON('http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?', {}, function (json) {
出てきた。App.vueというファイルの中にある該当行をターミナルに出力してくれた。この結果を更に別のコマンドの入力にすることもできる。
ここで出てきた find
|
xargs
grep
は、それぞれ単機能しか持たない独立したコマンドであり、お互いの存在は知らない。しかし、あるコマンドの結果を別のコマンドの入力として渡して…と、それらを組み合わせる、一連のフィルタ処理としてコマンド群を使うことによって一つの仕事ができた。これがRPAでやりたいことではなかったのか?
ちなみに上記の呪文はこのような意味:
find
ファイル検索。”.”でカレントディレクトリを検索、”*”は全ての拡張子のファイルの意味|
パイプ。左側コマンドの出力結果を右側コマンドの入力に渡すxargs
入力をコマンドライン引数にして次に来るコマンドへ渡すfind
全文検索。引数の文字列を検索する
これを1つ1つ実行して、あるコマンドの出力を手動でコピーして、また次のコマンドの引数にして渡して…とすると人力と手間、時間が掛かるので、このように一度に処理すれば時間と労力を節約できる。これをもっと複雑にして、条件による処理を分けたいのなら、各種シェルスクリプトを書くことが出来る。これはRPAそのものではないか?
ここで扱うデータが上記のようにテキスト形式であれば、どのようなアプリからでも開くことが出来るし、例えばHTML形式のように構造が決まったテキストファイルのフォーマットで書いてくれれば、中の構造は他の開発者にも理解できる。対するMicrosoft Officeのデータフォーマットは最近まで企業秘密であり*1、Officeファイルを扱うサードパーティーは何とかしてそれを解析していたけど、100%互換性があるとは言い切れなかった。
*1) ネットで探したらXSLXフォーマットはXML形式をzip圧縮したものらしいので、面倒だが解析は可能だ
Excelを自動化したければ、内蔵VBAで書けば良い(20年間開発が停止した非力な言語であるけど仕方がない)。関数だけでも良い。しかし、あるデータをExcelに貼り付けて、それを加工して、結果を別のシステムの入力にして…のような複数のアプリの間でデータをやりとりして一つの仕事が完成するような業務では、途端にどうすればよいのか分からなくなる。
そこで私のような、ソフトウェア・エンジニアに仕事を頼むことになる。事務員はUNIXの呪文のようなコマンドは知らないし、Excel関数を使って業務を効率化する前任担当者の知恵が詰まったExcelブックを前任から言われるがままに操作しているだけなので、誰もメンテナンスできない。
ここで昨今のRPAの考え方では「業務内容が変わり続ける状況にあって、事務員あるいはそれに近い担当者がRPAのシナリオをメンテナンスできた方が良い」との考えが出てくる。そこで、例えばWinActorのような「フロー図を繋ぎ合わせる方がコードを書くより簡単であろう/非ソフトウェア・エンジニアでもメンテナンスできるだろう」と結論づけるのだそうだ。
大間違いだ
「コードを書くよりフロー図を繋ぎ合わせる方が簡単だ」との考えは大昔からあった。その考えに沿った製品も沢山あった(Prograph CPXって知ってる?)。しかしいま現在、それらは何一つ残っていない。失敗したからだ。
なぜ失敗したか?コードを書くほうが簡単で、早くて、パワフルだからだ。あなた、業務を自動化したいのでしょう?それも早く、複雑な仕事を、フレキシブルに扱いたいのでしょう?フロー図じゃ無理だね。
コードの書き方もフロー図の書き方も知らない人がいたとして、学習曲線はどちらが上だろうか?同じくらいではないか?そして一度慣れたら、コードで書くほうが遥かに早いしパワフルだ。急な変更にもすぐに対応できる。
パワフルとかパワーとか、プログラミング言語にそのようなものがあるのか?と疑った方はこれを見てほしい:
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLO.
000300 PROCEDURE DIVISION.
000400 DISPLAY 'HELLO, WORLD!'.
000500 STOP RUN.
COBOLでのHello, Worldの例。Wikipediaより。
puts 'Hello, World!'
RubyでのHello, Worldの例。
プログラマーが好むのはどちらだろうか?当然、後者だ。同じ処理をしたいのなら、手数が少ない方が良い。なぜなら人間が一度に把握できるコードの量には限界があり、私のような脳がどこかおかしな人間は平均よりメモリ容量が更に少ないので、どうしようもなく簡単な処理には、どうしようもなく簡単に実現できないと混乱してしまう。この、簡単な処理を簡単に、複雑な処理も少しは簡単に書けることを、プログラミング言語におけるパワーだと思ってほしい。
WinActorに限った話で申し訳ないけど、同ツールで1つのシナリオに使える変数は256だか260だか、その程度だ。たったそれだけ?この64bit CPUが最大16エクサバイトまでメモリを使えるようになった現代で、たったそれだけ?私が小学生の頃に触ったMSX(メインメモリ64KB)じゃないんだから、この2020年で変数に上限値を設けられるとは思わなかった。しかも組み込み系ではなくPC系で。
しかも変数は全てグローバル変数だ。グローバル変数は敵、非構造化は敵であるとしてローカル変数が使えるようになった「構造化BASIC*2」であるMicrosoft Quick Basicの発売は1985年だそうだ(Mac発売の1984年の翌年にはサポートされていた)。これが後のVisual Basicに続き、1990年代に全盛を迎え、20年間放置され、未だに使われ、ソフトウェア・エンジニアが泣いている。
*2) 行番号の廃止、ローカル変数と関数を導入したBASICのこと
参考文献:Macintoshの理屈 冨山 学 (著)
全てグローバル変数なんて、それより時代が遡るのか。小学生の頃に買った「アドベンチャーツクール」の内蔵言語がそんな感じだった。
グローバル変数で定義できる256だかはすぐに上限に達し、仕方がないので同じ変数を別の意味で使いまわし、この変数がどのタイミングで何の意味で何の値が入ったのか分からなくなり、シナリオは動かなくなる。ちなみに変数には配列…のようなものもあるが、あんなものは配列ではない。
ノードはVBScriptで書かれているので自分で書けないこともないが、これも20年間放置された非力な言語だ。私はVBAとVBSの細かな違いなど知らない。
1980年代に、既にバグの温床と見做されて捨てられた「すべてグローバル変数」をこの2020年に復活させて、バグを生み出し、カスタマイズしたいのなら20年間放置された非力な言語で書かせ、それをソフトウェア・エンジニアではない素人がメンテナンスするのだそうだ。これはもう、失敗しろと言っているようなものじゃないか。
グローバル変数は、どこからでも変数の値を変更できるために、処理が大きくなるとすぐに制御不能になってしまう。ローカル変数は、その変数の有効範囲を関数内にとどめておくことで、別の関数の処理を書いている間は、別のローカル変数に対しては何も考えなくてもよい。コンピューターにメモリ容量があるように、人間の脳にもメモリ容量がある。私の脳は特にそれが少ないと感じているから、常にシナリオの全てのノード、すべての変数の状態を把握しながら作るなんて不可能だ。単機能を持つ関数に、使用する変数を全て閉じ込めておく。実装が終わったら、それをテストする。テストに合格すれば、あとは関数の中身など記憶からさっぱり消す。「これは何々という処理を行う関数だ」と自然言語で一言、覚えておけば後から利用できる。
すべてがグローバル変数であるなら、どのような状況でも関数が正しく動く保証などできない。ちなみにWinActorに関数という概念は無く、すべてはサブルーチンだ。小学生の頃に触った、MSX-BASICを思い出す。若者の皆さん、1980年代にようこそ!ジャケットには肩パット入れてね。
つまりWinActorは、もとより大規模で複雑な処理などできる設計ではない。
ノーコード?ローコード?が好きなのですね?「ファイルパスをパスとファイル名に分割してファイル名のみ変更する」といった手順ですが、WinActorなら標準機能では対応できません(外部ライブラリを使って3ノード掛かる)。PythonとかRubyといった、そこらのスクリプト言語なら1行で書けます。これが「ローコード」ではないのか?
「アホな人類が十分に対処できると感じていた原始的な武器(Java, C#, Ruby, Python)による抵抗の試みはすぐに失敗した」つまり人類のショボい武器じゃバグには勝てないってLand of Lispのコミックにも書いてあるじゃねえか、読んでないのか。ではなぜ関数型言語がバグに勝てるのかと言うと冪等性を持った関数を書くことも出来るからだ。
当然、注意すれば上記コミックで書かれた武器でも冪等性は可能だが、全てがグローバル変数である場合、それは不可能だ。
自然言語に近い方が、ノーコード環境の方が簡単だという業界全体の誤解が1990年代初頭まであった。しかし今どきそれを言うか?
データベース問い合わせクエリ言語であるSQLや、BASICが自然言語(この場合は英語)に近いことから1960–1990年代初頭まで「自然言語に近いほうがプログラミング言語は学習が容易だ」との誤解が業界全体に蔓延していたように思う。しかし2020年末の今にして思えば、それこそが誤解だったのではと感じる。1980年代までは低レベル言語といえばマシン語かアセンブリ言語であり、それに比べてSQLやBASICは自然言語に近いから習得が容易であると(この考えの延長線上に<フロー図言語は習得が容易>の誤解がある)。
しかしアセンブリ言語と高級言語を分けたのは、その構文ではなく、単に「パワフルか否か?」だけの問題だったのではないか?確かに、数十年前の少ない計算機資源であっては低レベル言語の方が実行速度が速い、という基準での「パワフル」でもあったのだろうが、今の基準は「少ない行数で多くの仕事ができる」ことを「パワフル」であると考えると、「多くの手順で少ない仕事しかできない」ツール/言語はパワフルではない、と評価できる。そして、ある仕事をするために書かなければならない行数が多ければ多い言語ほど「難しい」と言って良いのではないか?「BASICはPRINT文1行で画面に文字列を出力できる。しかしアセンブリ言語ではメモリを確保して…と同じ仕事をさせるのにプログラマーが何行も書かなければならない」。これは難易度ではなく簡易性の問題では?それを皆は「簡単/難しい」と、基準を間違えて語っていたように思う。
その基準で言うと、コレクションフレームワークですら標準機能ではないVBScriptやらMicrosoft系BASIC一族こそ、難しい言語であると言える。
Pythonには「電池付属 (“Battery Included”)」という思想があり、プログラマがすぐに使えるようなライブラリや統合環境をあらかじめディストリビューションに含めるようにしている。このため標準ライブラリは非常に充実している。
https://ja.wikipedia.org/wiki/Python
必要なものが、最初から用意されている言語こそ「易しい」言語だ。コードは書かないが、何も用意されていない言語は「難しい」というか「面倒くさい/時間がかかる/パワフルではない」。
星の数ほどあるプログラミング言語の、それぞれ何が違うのかといえば、実行する相手がゼロかイチかしか分からない相手であるから、そう大きな差などない。実行速度の差など、計算機資源を富豪的に使えば良いだけだ。そうなれば、「現代基準でのパワフルな言語」を使わない手はないというか、未だに1990年代初頭までの誤解を引きずって「初心者向け言語」とやらがあると信じる連中は、その後のプログラミング言語の趨勢やら、コンピュータとは何であるかといった深い理解が欠けたまま年を取り、エンジニアリングではない分野が得意だったので予算を決定できる役職に就いただけではないか。そのような連中がどのツールを導入するのかを先に決めてしまうと、後で泣くのが現場作業者であるプログラマーだ。少なくとも技術に関しては技術者の方がより良い正解を知っている。こっちは職人なんだ。審美眼のない素人はすっこんでろ、という気持ちがある。
失敗するのが目に見えているプロジェクトに参画することは、勝つ見込みのない戦争に駆り出されるのと同じ虚しさを感じる。どうせ死ぬなら少しでも勝率が上がるように、その時点での最強の武器をくれよ。じゃないと犬死にだ。私は昔の日本人のように「死ぬために戦う」などという目的を見失った考えはしない。私はプロジェクトを成功させるために参画しているのだ。
上記、横浜市の「事務作業にかかる時間が最大99.1%削減」は、RPA開発や運用、メンテナンスの時間を全く考慮していない。そりゃ実行時間だけ比べればそうだろうよ、としか思わない。VLOOKUP関数も知らない事務員が「Excelの特定シートの1000行から目視でセルを探し出して別シートに書き出す」ような作業を自動化した場合、「最大99.1%削減」と言われても、今までの作業の仕方が悪かったことが原因であり「本来なら作業時間を1/100に縮められたが事務員の無知から恐ろしく非効率な方法で仕事をしていた」というものだろう。RPAとは全く関係ない。
伝説の「Excelで計算した後、手元の電卓で検算するおじさん」がいるかどうかは知らない。
2番目の記事にあるように、RPAってすぐ止まりますよ。とにかくGUIのような非同期処理のオートパイロットなど苦手中の苦手なのに、それをやれだなどと…。長期的に見れば、操作するWebシステムにCLIからリクエストを投げられるREST APIを実装することの方が長期的に見れば時間の短縮になる。
複数行あるソースを自動化スクリプトに処理させる。全10行のうち、5行目で止まった。さて、1–4行は無事にシステムに登録されただろうか?
登録しちゃ駄目だろ。世の中のDBMSが、INSERTに失敗したらロールバックする理由は「プログラマーは完全成功の状態と完全失敗の2つの状態の場合の処理のみ書けばよい」状況にしたいからであり、途中で失敗して、その不完全なデータの後片付けを誰がやるんだよ。こういうのはRPAに食わすな、DBでやれ。
魔法のツールなど無い
- 1990年初頭に私がPrograph CPXを雑誌で見た時、当時の私はあまりコードを書けなかったので、これさえあれば自分でもアプリを作ることが出来るのではないか?と妄想したものだけど、結局、苦労してC++を勉強したら、明日のメシにありつけた。理解が難しいと初心者を脅していたCのポインタもC++で覚えた。
- フロー図でコーディングの代わりをする系の開発環境が成功しないことは歴史が証明している(超高速開発ナントカとか…NECやらCanonやら大企業の優秀な皆様が馬鹿をやるエイプリルフールだろうか)。
- よって、現在盛んに資金を集めているノーコード/ローコード開発環境により、ユーザーが自分の処理を自動化する処理を書く未来は来ない。
- プログラミング言語にはそれぞれ固有の力(Power)があり、どの道具を使うのか?と言われたら、「一番強いやつをくれ」と言うのは当然だろう。正規表現が組み込まれていれば1行で取れる処理を、わざわざ200行書きたいか?
- すべてがグローバル→構造化・ローカル変数化→オブジェクト指向→関数型、のプログラミング言語の流れは、それまで無用なバグの原因究明に流れた汗と涙と先人の知恵が歴史になっているのだ。その歴史を全部無視しないでくれ。歴史に学べない者は愚か者である。
- ポール・グレアムは、もっとも力(Power)のあるプログラミング言語はLispだとしたが、もしLispを採用するとしても、そのプログラマーを雇うのに苦労してしまう。アメリカならボストンのMIT周辺、日本なら京都大学の周辺に生息する灰色の魔法使いたちを雇うことになりそうだから、これはエンジニア確保の面からも現実的ではない。でもPythonプログラマーくらい、いくらでもいるだろう。もっともグレアムはPythonよりRubyの方がより関数型的、Lisp的であるとして評価しているけど。
結論
- RPAは特別な製品などなくても、ありあわせのツールで十分作れる、というかその方がよほどパワフルで早いし、柔軟だ。
- フロー図、ローコード、素人でもできる…。その地雷、私達オッサンが過去に全部踏み抜いた後なのに、またやるの?
- 業務の自動化について、PythonやらRubyやら、無料のオープンソース系ツールを私に与えてくれればノーコード/ローコードの10倍の速さで書いてあげるよ。それでメンテナンスする人員を確保できないなどと言うのなら、元々その地方にはソフトウェア・エンジニアなぞいないのだから大都市に仕事を振ってくれ。
- 大きな畑を耕すとしたら、トラクターと鉄の鍬、どちらが良いか?
企業・自治体の皆様におかれましてはくれぐれも「ベンダーがライセンスだけ売って逃げ切る」罠に陥らないよう、技術選定には慎重になっていただけますようお願いします。