何年も前、そしてLokad設立後も長い年月が経った後、サプライチェーン最適化に関しては、どんな一つのアプリも卓越した結果をもたらすことはあり得ないと気づきました。私たちは最善を尽くしましたが、それでも十分ではありませんでした。初期のLokadにどれだけ多くの機能を盛り込んでも、新たなクライアントはこれまでに対応したものとは全く異なる姿を見せました。供給チェーンの課題はあまりにも多様で混沌としており、健全な数のメニュー、ボタン、オプションに収めることはできないのです。

プログラミング言語Pythonとは無関係なパイソンのヘビ

実際、多くの競合他社もこの状況を認識しており、絶望的な試みとして、途方もない数のメニュー、ボタン、オプションを備えたソフトウェア製品の構築という道を辿りました。しかし残念ながら、この道は、壮大な 失敗として、大規模に展開されたソフトウェアの怪物へと繋がってしまいます。私はこのアンチパターンを非ユークリッドの恐怖と呼んでいます。

このように、単一_のアプリでは解決不可能な、すなわち供給チェーンの課題という一連の問題に直面し、私たちは部分的に偶然1にも、代わりに_メタ問題、すなわち各アプリが特定の状況下の単一の問題解決に専念する_カスタムアプリ_をどのように提供するかという問題に取り組み始めました。例えば、特定企業向けの補充最適化などです。

企業向けにカスタムソフトウェアを提供することは決して新しいことではありません。ソフトウェア業界は60年代にそのように始まり、後に80年代には今日私たちが知る支配的なシュリンクラップモデルへと進化しました。一般的に、カスタムソフトウェアはシュリンクラップに比べ、初期投資の増大、セットアップの長期化、維持管理費の上昇、リスクの増大など多くの望ましくない特性を持ちがちです。

しかし、Lokadの最初の数年間で得た経験は、供給チェーン最適化において、カスタムソフトウェアには_一つ_の大きな利点があることを示していました。それは、実際に_素晴らしい_結果をもたらすという点です。実際、私たちのオリジナルアプリは、いくら予測が正確でもせいぜい_並び_の結果に留まっていましたが、これらのプロトタイプはしばしば_素晴らしい_成果を上げていました。さらに、ここで必要だった唯一のコツは、対象となる問題に特化したソフトウェアの_極端な専門化_でした。

あらゆる代替案を尽くした結果、私たちはカスタムアプリの提供が唯一の道であると結論付けました。しかし、スケーラビリティ(いかに多くのアプリを提供するか)と_メンテナンス性_(維持管理費を抑制する方法)は、二大の核心的課題でした。 まず、_プログラミング言語_を選定する必要がありました。当時、私たちはR、Python、JavaScript、Lua、C#など多くの選択肢、そして後にEnvisionとして知られる自社ドメイン固有プログラミング言語(DSL)の開発を検討しました。それらすべての長所と短所を議論するのは少々冗長になる2ため、明快さを保つために、議論はPythonとEnvisionの選択に絞られ、Pythonが自社DSL開発に対する最有力候補でした。

Pythonはそのシンプルさと、特に機械学習分野における豊富なサードパーティライブラリのエコシステム3によって魅力的でした。また、Pythonおよびその主要なライブラリはほぼすべてオープンソースであるため、Lokadにとっては_低コスト_の選択肢でもありました。つまり、私たちはPythonの狭いサブセットを再パッケージし、数十の厳選パッケージをホワイトリスト化するだけで済んだでしょう。Lokadの作業の大半は、HerokuのようなPython中心のPaaS体験を提供し、供給チェーンの課題に極力沿わせることに注力されました。

しかし、私たちが検討したリトマス試験があります。すなわち、ビジネスアナリスト—後にサプライチェーン・サイエンティストと呼ばれる—が、週に1日、6か月働いて、1000万ドル規模の企業のために補充など、事業上極めて重要な供給チェーンの課題を解決するプロダクショングレードのアプリを提供することが合理的かどうかというものでした。Pythonの選択肢を検討した時点で、そのような運用効率に近づくことは到底不可能だと明らかでした。

まず第一に、Pythonはソフトウェアエンジニアを必要とします。実際、Pythonは完全なプログラミング言語として、コードを書く人に膨大な技術的複雑さを晒します。供給チェーン・サイエンティストの役割が後になって正式化されたにもかかわらず、初期の段階で、優秀な人材であっても供給チェーン工学とソフトウェア工学の両方の専門家であることを期待するのは無理があるという直感がありました。私たちは、プロのソフトウェアエンジニアだけでなく、技術に精通した広範な人々が利用できるプログラミング能力を求めていたのです。

このように、Pythonでは避けられない一連の技術的問題を根絶するために、Envisionという言語を作り上げました。例えば:

  • オブジェクトは_null_になり得るし、日付は途方もなく過去や未来へ飛躍し、NaNはデータパイプライン内で喜んで伝播し、文字列は途方もなく大きくなる可能性があります…供給チェーンにおいて、これらの「特徴」は、すべて問題の種に過ぎません。
  • オブジェクト指向の要素(すなわちクラス)は必ず誤用される4とされ、カスタム例外や正規表現についても同様です。それらの要素の存在自体が、せいぜい不健全な気を散らす要因となります。
  • 異なる形式の表形式ファイル(Excelスプレッドシートを含む)の解析などの基本操作は言語自体に組み込まれておらず、多くの異なるパッケージを扱う必要があり、それぞれが固有の技術的複雑さを帯びています。

これらの技術的問題のいずれも、言語自体を損なわずにPythonから取り除くことはできません。Envisionは、プログラミング言語として、供給チェーン専門家(対して_ソフトウェア専門家_ではなく)が利用できるのは、_予測型供給チェーン最適化問題_に対する極めて鋭いフォーカスのおかげです。

最後にExcelスプレッドシートで計算を行った時のことを思い出し、自分がそのスプレッドシートを直接見ることなく、電話越しにすべての変更を指示した状況を想像してみてください。これが、実務者が推進し、供給チェーンの専門家でないソフトウェアエンジニアによって実装された供給チェーン最適化プロジェクトの実態なのです。ビジネスはITに何を求めるかを伝えるのに膨大な時間を費やし、ITはビジネスの要求を読み解くのに膨大な時間を費やします。Lokadでの十年の経験から、供給チェーン専門ではないソフトウェア開発者に量的供給チェーンマニフェスト最適化のプロジェクトを任せると、どんなにアジャイルで才能あるチームでも、コストが少なくとも5倍に跳ね上がることが分かりました。

次に、急ごしらえのPythonプロトタイプの保守費用は天文学的に高騰します。ソフトウェア業界外では、ソフトウェア工学5が主に保守費用の管理に関するものであることに気付いている人はほとんどいません。しかし、供給チェーン最適化の問題を解決するのは非常に混沌としたプロセスです。多くの(あまり信頼性のない)システムからのデータを確実にパイプライン処理し、不完全で常に変動するプロセスを文書化・モデル化し、最適化指標が絶えず変化するビジネス戦略を反映する必要があります。その結果、どのソフトウェアも供給チェーン最適化を実現するために書かれると、一種のドメイン固有の複雑さが大量に内在し、単に現実世界が投げかける問題に対処するだけのものとなってしまうのです。

しかし、時間は極めて重要です。昨年の生産計画のために完璧なプランを立てる意味はありません。一般的に、ソフトウェアプロトタイプが動き始めたその日には、プロトタイプが上手く書かれているかどうかに関わらず、数週間以内に本番環境へ移行されると考えてよいのです。

上級管理職が、保守の観点からプロトタイプを書き直してプロダクショングレードにするために6か月の遅延を承認することを期待するのは夢物語です。しかし、急ごしらえのPythonプロトタイプを本番環境に投入することは、途方もない保守コストと、絶え間ないバグの猛攻(24時間体制で応急処置を施さなければならない)を招く結果となります。

このように、本番環境を健全に保つ唯一の実用的な方法は、設計段階から高い_正確性_を保証するプログラミング言語でプロトタイプを作成することです。例えば、Pythonとは異なり、Envisionは以下の点を実現します:

  • コンパイル時に保証される_有限の実行時間_:数テラバイトのデータを処理する際、計算が決して終了しないと分かるまで何時間も待つのは非常に骨の折れる作業です。 コンパイル時に保証される限定的なメモリ使用量:夜間の本番バッチでメモリエラーに苦しむのは全く楽しくなく、実際に運用を著しく混乱させます。
  • アトミックな読み書き:Envisionは、スクリプト実行中にFTPでファイルが転送されている場合であっても、ファイルシステム内での同時読み書きを設計上から防ぎます。Envisionを支えるファイルシステムは、巨大なフラットファイル向けに特化したGitのようなものです。適切な_データ_バージョニングがなければ、多くのバグはハイゼンバグに変わってしまいます。なぜなら、誰かが問題に取り組む頃にはデータが更新され、問題を再現できなくなっているからです。
  • _クラウド_上のコンピューティングリソースを利用した_アンビエントなスケールアウト_実行により、データが数十ギガバイトを超えた時に避けられない並列化の障害をすべて取り除きます。

一般的なプログラミング言語は、設計に基づく正確性をほとんど提供せず、またPythonは遅延バインディングに大きく依存しているため、この点で提供されるものは極めて少ないのです。設計段階からの正確性という観点でRustのようなより優れた代替案を考えたとしても、供給チェーン最適化にとっては全く十分とは言えません。

ここに、EnvisionがPythonでは決して実現できない形で輝く、さらにいくつかの分野を示します:

多層防御:組織内で誰かがコードを書き始めると、特別な予防措置6が講じられない限り、そのコードはITセキュリティの観点から即座に重大なリスクとなります。Pythonを用いれば、Pythonスクリプトを実行しているマシン上でほぼ何でも可能となってしまいます。実際にPythonを適切にサンドボックス化するのは途方もなく複雑な問題です。特に、Pythonスクリプトが出力する任意の文字列は潜在的なインジェクション経路となります。SQLインジェクションが悪名高いのと同様に、CSVのような単純なテキストファイルでさえ、インジェクション攻撃に対して脆弱であることに気付く人は非常に少ないのです。Envisionは、Pythonでは実現不可能なレベルのセキュリティを提供します。データ漏洩が増加する中、Pythonの断片があちこちに放り出されても、ITセキュリティの向上には到底寄与しません。

透明なパフォーマンス:もしプログラムの実行速度が非現実的に遅いのなら、そのプログラムは最初からコンパイルされるべきではありません7。もしプログラムが1行短くなれば、実行速度は速くなるはずです。たった1行だけが変更された場合、その行だけが再計算されるべきです8。コンパイル時には、コンパイラは特定のマシンではなくコンピューティングリソースのクラウドを対象とし、自動的なデータ駆動型並列化を実現すべきです。Envisionは、これらすべての特性を、いかなるコーディング努力も必要とせず、デフォルトで提供する大きな一歩を踏み出しています。一方、Pythonではこれらに近づくために大量の専門ライブラリの使用が必要です。

透明なアップグレード:ソフトウェアにおける最先端技術は、常に移り変わる目標です。2010年には最高の機械学習ツールキットはSciPy(議論の余地はありますが)、2013年にはscikit、2016年にはTensorflow、2017年にはKeras、2019年にはPyTorchでした。ソフトウェア工学では、ソフトウェアスタックとその依存関係を見ることで、そのプロジェクトの誕生年を推定できるという諺があります。実際、独自のPythonスクリプトを展開すれば、経年劣化する可能性のある複数の依存関係を抱えることになるのです。それに対し、Envisionでは自動コード書き換え9を広範に活用し、「レガシー」なスクリプトを常に変化する言語に合わせて最新の状態に保っています。

パッケージ化されたスタック:Pythonスクリプトは真空中では動作しません10。コードはバージョン管理(例:Git)され、アクセス権(例:GitHub)が必要です。コードは自分のマシンではなく、実行環境(例:クラウド上のLinux VM)が必要です。データパイプラインを調整するためのスケジューラ(例:AirFlow)が必要であり、データ準備のためには分散型のカラム型ストレージ層(例:Spark)が必要です。予測分析には機械学習ツールキット(例:TensorFlow)が必要で、供給チェーンの組み合わせ最適化には最適化ツールキット(例:GLPK)が求められます。さらに、生データの結果は後で利用できるようどこかに公開され、供給チェーンの実務者が状況を把握できるウェブユーザーインターフェースが必要です。アクセス権は必ず管理されなければならず(例:Active Directory)…など、数多くの要素が要求されます。Envisionはこれらすべてを一つのメタアプリに統合し、最も基本的なアプリでさえ提供するために多数のソフトウェア部品を組み合わせる負担を解消します。

とはいえ、優れた言語であるPythonにも、非難すべき点が存在します:

  • 計算性能が悪く、データ処理タスクで極めて低いパフォーマンスを回避するために、すべての計算を_適切な_ライブラリ(例:NumPy)に通すのは骨の折れる作業です。さらに、複数のライブラリを使用すると、データをあるライブラリから別のライブラリへ移す際に多くの摩擦が生じがちです。
  • メモリ性能も悪く、特にPythonの参照カウント方式のガーベジコレクションは_時代遅れ_であり、Java、C#、JavaScriptなどの最新のプログラミング言語では代わりにトレーシングが用いられています。大量データを扱うメモリ集約型タスクにおいて、これは大きな痛手となります。
  • Pythonのパッケージ管理は、大混乱状態で、長い間そうあり、正しく行うにはパッケージ専門家が必要です。また、この問題は高摩擦な言語アップグレードによってさらに複雑になっています.
  • 大部分の(ごくわずかな)正確性チェックはプログラム実行時の_runtime_にのみ行われ、データ処理においては終わりのない苛立ちの原因となります。明白な問題は実行後数分経過して初めて現れ、生産性を下げます.

結論として、Pythonは素晴らしい(確かにそうですが)ものの、サプライチェーン最適化に対する満足のいく解決策ではありません。Pythonで本番レベルの機械学習アプリを構築・保守することは十分に可能ですが、コストは大きく、もし会社がこのアプリの保守に少なくとも小規模なソフトウェアエンジニアチームを専任で配置する準備ができていなければ、全体としてサプライチェーンに満足のいく成果をもたらすことはありません.

予測的サプライチェーン最適化専用のドメイン固有プログラミング言語であるEnvisionの開発は、我々の第一選択ではありませんでした。第10の選択肢でもなく、むしろ5年間にわたってより一般的な代替案を試みた結果、唯一実現可能な解決策として残ったものでした。7年後、多くのクライアント企業を経ても、各新規クライアントは何らかの形でサプライチェーンに新たなひねりを加え、従来のエンタープライズウェア方式では到底対応できなかった驚きを提供します。プログラム可能性は必要でしたが、Pythonは我々が求めた解決策ではありませんでした.


  1. 2013年当時、サプライチェーン最適化において満足のいくアプリを提供できると考えていました。しかし、価格設定の課題との対峙が我々の手を縛り、Lokadを独自のドメイン固有言語構築の道へと導きました。当初、この言語は価格最適化専用を意図していましたが、すぐにこのアプローチこそがサプライチェーン最適化に必要なものであると実感しました. ↩︎

  2. 私たちがPythonにおいて特定した多くの問題は、Pythonそのものの問題ではなく(Pythonは優れたプログラミング言語ですが)、単にPythonが_汎用_プログラミング言語であるという事実に起因していました. ↩︎

  3. 2013年当時、Pythonはその後数年間で機械学習分野で獲得する支配的地位には達しておらず、Rは依然として有力な候補でした。しかし、SciPyとNumPyという二つの優れたライブラリは既に存在し、活躍していました. ↩︎

  4. 2012年のPyConでのこの優れた講演Stop Writing Classesをチェックしてみてください。経験豊富なソフトウェアエンジニアでさえ、間違いを犯しがちです. ↩︎

  5. _コンピュータサイエンス_とは対照的に、ソフトウェアエンジニアリングは本番システムの確実な運用に注力するものであり、一方でコンピュータサイエンスは高速なアルゴリズムの発見など、難解な問題の解決に取り組むものです. ↩︎

  6. 残念ながら、コードのセキュリティに関しては、体系的なピアレビューの代替手段はほとんど存在しません. ↩︎

  7. 停止問題により、注意深い読者はEnvisionがTuring完全な言語ではないと推測するかもしれません。実際、Envisionはそのような言語ではありません. ↩︎

  8. Envisionは計算グラフ間の差分に依存しており、大規模なデータセット上で非常に高速なプロトタイピングを可能にするため、増分的な変更間の再計算を最小限に抑えようと試みます。しかし、状況によっては、一行の変更がスクリプト全体の再計算を必要とする場合もあります. ↩︎

  9. 汎用プログラミング言語において、コードの自動リライトは極めて困難です。プログラミング言語とその全標準ライブラリがこの要件を念頭に置いて精密に設計されていなければ、自動アップグレードツールは実際にはほとんど効果を発揮しません。Envisionを設計する際、私たちは数多くの点で失敗するだろうと(実際にそうなりました)予測しており、そのため言語が自動リライトに特に適していることを確認するために多大な配慮を払いました。現在までに、Envisionの誕生以来、100回以上の増分リライトを実施しています. ↩︎

  10. 皮肉なことに、“Batteries Included”はPythonのモットーの一つです。しかし、予測的サプライチェーン最適化を目的としたアプリを構築するために必要な全ての要素を統合するための膨大な接着剤は、非常に困難です. ↩︎