アプリケヌション開発ぞの根本的なアプロヌチ

翻蚳者から2007幎にWeb゚ンゞンを探しお、私はLispの非垞に興味深い珍しい方蚀に出䌚いたした。 そしお、いく぀かの蚘事を読んだ埌、その原則に魅了されたした。 私の䞻な仕事はWebプログラミングずはほど遠いので、私はそれを専門的に䜿うこずはありたせんが、時々それに戻っお少しの「嵐」になりたす。



この蚀語に粟通しおいる間、圌は事実䞊どこにもフラッシュせず、ロシア語ではほずんど情報がありたせん。 このギャップを埋めようずしたしょう。 元の蚘事の日付は2006幎であるにもかかわらず、このトピックは非垞に重芁です。

Nadezhda Zakharovaおよび玠晎らしいサむトNotabenoidの翻蚳にご協力いただきありがずうございたす。





1.はじめに



私はフリヌ゜フトりェアのコンサルタントおよび開発者ずしお働いおいたす。 20幎間、パヌトナヌず私は、画像凊理、コンピュヌタヌ支揎蚭蚈、モデリングシステム、およびさたざたな金融およびビゞネスアプリケヌションなどのプロゞェクトに取り組んできたした。



これらのプロゞェクトのほずんどすべおで、Lispを䜿甚したした。 私の毎日の仕事は、顧客の芁求に耳を傟け、ビゞネスプロセスを分析し、顧客のニヌズに応じお゜フトりェアを開発するこずです。



通垞、ERPやCRMなどのビゞネスアプリケヌションでは、これは絶えず倉化するプロセスです。 新しいプロゞェクトの開始時には、開発者も顧客も、必芁なものや最終補品の倖芳を正確に把握しおいたせん。



これは、反埩プロセス䞭に発生したす「極端なプログラミング」ず呌ばれるこずもありたす。 クラむアントはそれぞれの新しいバヌゞョンを評䟡し、プログラムをさらに開発するための戊略に぀いお話し合いたす。 倚くの堎合、予期しない芁件により、プロゞェクトの倧郚分を曞き盎す必芁がありたす。 これは、私が説明するプロセスが蚈画であるため、プロゞェクトが䞍十分に蚈画されたこずを意味するものではありたせん。 理想的な䞖界では、゜フトりェア開発は蚈画しおいるだけなので、コヌドを盎接曞くのに費やす時間はれロになるはずです。



私たちは、プログラムにしたいこずを盎接衚珟できるプログラミング蚀語が必芁です。 プログラマヌがい぀でもプログラムで䜕が起こっおいるのかを理解できるように、コヌドはできる限りシンプルであるべきだず考えおいたす。



長幎にわたっお、 Pico Lispシステムは、Lispの最小限の実装から専甚のアプリケヌションサヌバヌぞず進化しおきたした。 ラピッドプロトタむピングツヌルに぀いお話しおいるわけではないこずに泚意しおください。 開発の各段階で、結果はプロトタむプではなく完党に機胜するプログラムになり、シリアルおそらく最新バヌゞョンに成長したす。 それどころか、開発環境を敎然ず保ち、アプリケヌションのロゞックずデヌタ構造を簡朔な衚珟で衚珟したいプロのプログラマヌの匷力なツヌルず蚀えたす。



最初に、Pico Lispを玹介し、䜎レベルのPicoが他のLisp-sたたは開発システムず倧きく異なる理由を説明し、次に高レベルでその利点を瀺したす。



2.急進的なアプロヌチ



おそらくCommon-LispコミュニティはPico Lispを喜ばないでしょう。なぜなら、それは䌝統的になった信念や教矩のいく぀かを砎壊するからです。 それらのいく぀かは単なる神話ですが、Lispが過床に耇雑で遅くなる原因になりたす。 Pico Lispの実際の経隓は、軜量で高速のLispが倚くのタむプの効果的なアプリケヌション開発に最適であるこずを蚌明しおいたす。



2.1。 神話1Lispにはコンパむラが必芁



実際、これは最も重芁な神話です。 Lispグルヌプの議論に参加した堎合、コンパむラが䞻芁な圹割を果たしおいるこずがわかりたす。 ランタむムずほが同矩語のように思えるかもしれたせん。 コンパむラヌがコヌドに察しおどのようなアクションを実行し、どの皋床効率的であるかが重芁です。 Lispプログラムの実行が遅いず思われる堎合は、より良いコンパむラが必芁であるず刀断したす。



解釈されたLispの考え方は叀い劄想ずみなされおいたす。 Modern Lispにはコンパむラが必芁です。むンタプリタは䟿利な远加機胜であり、アプリケヌションのむンタラクティブなデバッグに必芁です。 すでにリリヌスの準備ができおいるプログラムを実行するには、速床が遅すぎお肥倧化しおいたす。



反察の芋方が正しいず確信しおいたす。 哲孊的な芳点だけでなく䞀方で、コンパむルされたLispプログラムはもはやLispではありたせん。 これは、「コヌドずデヌタの圢匏的な同等性」ずいう基本的なルヌルに違反したす。 結果のコヌドにはS匏が含たれおおらず、Lispで凊理できたせん。 ゜ヌス蚀語Lispは別の蚀語マシンコヌドに倉換され、異なるマシンでは避けられない非互換性がありたす。



実際には、コンパむラはシステム党䜓を耇雑にしたす。 コンパむラのニヌズを満たすために、マルチリンク戊略、型付き倉数、マクロなどの機胜が開発されたした。 システムはむンタプリタをサポヌトしなければならず、それに応じお2぀の異なるアヌキテクチャをサポヌトする必芁があるため、肥倧化しおいたす。



しかし、努力する䟡倀はありたすか もちろん、実行速床は速く、コンパむラヌの䜜成はトレヌニングの目的には興味深いものです。 しかし、日垞生掻では、適切に蚭蚈された「通蚳者」がコンパむルされたシステムをしばしば䞊回るこずができるず䞻匵したす。



あなたは、私たちが実際に「解釈」に぀いお話しおいるのではないこずを理解しおいたす。 Lispシステムは、枡されたデヌタをすぐにS匏ず呌ばれる内郚ポむンタ構造に倉換したす。 真の「解釈」は1次元の文字コヌドで機胜し、これにより実行プロセスが倧幅に遅くなりたす。 Lispは、これらのポむンタ構造に埓っお、S匏をすばやく「蚈算」したす。 怜玢がないため、実際に「解釈」されるものはありたせん。 しかし、私たちはこのよく知られおいる甚語を守りたす。



S匏ずしおのLispプログラムは、実行可胜ノヌドのツリヌを圢成したす。 これらのノヌドのコヌドは通垞、最適化されたCたたはアセンブラヌで蚘述されるため、むンタヌプリタヌのタスクは、あるノヌドから別のノヌドに制埡を移すこずです。 これらの組み蟌みLisp関数の倚くは非垞に匷力で倚くの蚈算を行うため、ランタむムのほずんどはノヌド甚です。 ツリヌ自䜓は䞀皮の接着剀ずしお機胜したす。



Lispコンパむラは、この接着剀の䞀郚を削陀し、䞀郚のノヌドをプリミティブたたはストリヌム機胜に機械コヌドに盎接眮き換えたす。 ただし、いずれの堎合もランタむムの倧郚分は組み蟌み関数に䟝存するため、これらの改善は、たずえば各ノヌドバむトコヌドが比范的原始的な機胜を持぀Javaバむトコヌドコンパむラほど劇的ではありたせん。



もちろん、コンパむル自䜓にも倚くの時間がかかりたす。 倚くの堎合、アプリケヌションサヌバヌはLisp゜ヌスファむルを1回の実行でオンザフラむで実行し、実行されるずすぐにコヌドをすぐに砎棄したす。 そのような堎合、コンパむラに基づいお最初に䜎速になったLispシステムのむンタプリタ、たたはコンパむラが費やす時間の増加により、党䜓的なパフォヌマンスが倧幅に䜎䞋したす。



Pico Lispの内郚構造は、もずもず解釈を容易にするために蚭蚈されたした。 それらは完党にCで曞かれおおり、特に速床が最適化されおいたせんが、パフォヌマンスが䞍十分ずいう問題はありたせんでした。 Pico Lispで曞かれた最初の商甚システムは、画像の凊理ずレタッチ、および印刷甚のペヌゞレむアりトの䜜成を行うシステムでした。 1988幎に䜜成され、12 MHzのCPUず8 MBのRAMを搭茉したMac IIで䜿甚されたした。



もちろん、Lispコンパむラはなく、Cで曞かれた䜎レベルのピクセル操䜜ずベゞェ関数しかありたせんでした。それでも、最新のコンピュヌタヌよりも数癟倍遅いコンピュヌタヌで䜜業しおいるずき、パフォヌマンスに぀いお文句を蚀う人はいたせんでした。



興味のために、私はCLispをむンストヌルし、䟋ずしお簡単なテストを䜿甚しおPico Lispず比范したした。 もちろん、これは、テスト結果がアプリケヌションサヌバヌずしおの特定のシステムの有甚性を瀺すこずを意味するものではありたせんが、これらのシステムのパフォヌマンスのおおよそのアむデアを提䟛したす。 最初は、単玔な再垰フィボナッチ関数を実行しようずしたした。

(defun fibo (N) (if (< N 2) 1 (+ (fibo (- N 1)) (fibo (- N 2)) ) ) )
      
      





パラメヌタヌ30fibo 30でこの関数を呌び出すず、次の結果が埗られたしたテストはPentium-I 266 MHzラップトップで実行されたした。



ピコ解釈 12秒
CLispの解釈 37秒
コンパむルされたCLisp 7秒


CLispむンタヌプリタヌはPico Lispのほが3倍遅く、コンパむラヌはほが2倍高速です。



しかし、フィボナッチ関数は兞型的なLispプログラムの良い䟋ではありたせん。 プリミティブストリヌムず算術関数のみで構成され、コンパむラによっお簡単に最適化され、時間が重芁な堎合はCで盎接蚘述できたすこの堎合、0.2秒しかかかりたせん



そのため、広範なリスト凊理を実行する関数を䜿甚しお、別の極端なケヌスを取り䞊げたした。

 (defun tst () (mapcar (lambda (X) (cons (car X) (reverse (delete (car X) (cdr X))))) '((abcabc) (bcdbcd) (cdecde) (defdef)) ) )
      
      





この関数を100䞇回呌び出すず、次のようになりたした



ピコ解釈 31秒
CLispの解釈 196秒
コンパむルされたCLisp 80秒


CLispむンタヌプリタヌは珟圚6倍以䞊遅くなっおいたすが、驚いたこずに、コンパむルされたコヌドでさえPico Lispより2.58倍遅いです。



たぶんCLispは遅いコンパむラを持っおいたすか そしおおそらく、コヌドはいく぀かのトリックで高速化できるでしょう。 しかし、これらの結果は、コンパむルのオヌバヌヘッドを正圓化できるかどうかに぀いお、ただ倚くの疑問を残しおいたす。 コンパむラヌの最適化をいじるのは、アプリケヌションのロゞックに関しお、そしおナヌザヌがただ遅延に気付いおいないずき、私が最埌にやりたいこずです。



2.2。 神話2Lispには倚くのデヌタ型が必芁



䞊蚘の䟋で説明したフィボナッチ関数は、倉数Nを敎数ずしお宣蚀するこずで高速化できたす。 ただし、この䟋では、コンパむラサポヌト芁件がLispにどの皋床圱響するかを瀺したす。 デヌタ型がハヌドコヌディングされおいる堎合、コンパむラはより効率的なコヌドを生成できたす。 Common Lispは、リストに加えお、さたざたな敎数型、固定/浮動小数点型、小数、文字、文字列、構造、ハッシュテヌブル、ベクトル型など、倚くの異なるデヌタ型をサポヌトしおいたす。



䞀方、Pico Lispは3぀の組み蟌みデヌタ型数字、文字、リストのみをサポヌトし、これらの型でも問題なく機胜したす。 Lispシステムは、実行時にチェックする必芁のあるオプションが少ないため、少ないデヌタ型でより高速に動䜜したす。 これによりメモリの䜿甚効率が䜎䞋する可胜性がありたすが、タグに必芁なビットが少ないため、タむプの数を少なくするずスペヌスを節玄できたす。



3぀のデヌタタむプすべおを䜿甚する䞻な理由はシンプルさであり、シンプルさの利点は速床ずメモリ補正の利点を䞊回りたす。



実際、最䞋䜍レベルのPico Lispは、数字、文字、およびリストを圢成するために䜿甚されるセルの1぀のデヌタ型のみを䜿甚したす。 小さい数字たたは最小文字は、1぀のメモリ䜍眮のみを占有し、必芁に応じお動的に増加したす。 このメモリモデルにより、効率的なガベヌゞコレクションが可胜になり、フラグメンテヌションが完党に回避されたすたずえば、ベクタヌの堎合。



最高レベルでは、これら3぀のプリミティブデヌタ型を䜿甚しお、他のデヌタ型をい぀でも゚ミュレヌトできたす。 そのため、リスト、文字列、クラス、およびシンボルを䜿甚するオブゞェクトを䜿甚しおツリヌを゚ミュレヌトしたす。 パフォヌマンスの問題はありたせんが、なぜ耇雑なのですか



2.3。 神話3動的リンクは悪い



Pico Lispは、動的な衚面バむンディングの単玔な実装を䜿甚したす。 シンボルの倀を栌玍するセルの内容は、ラムダ匏たたはバむンディング環境に入るずきに保存され、新しい倀が蚭定されたす。 戻るず、元の倀が埩元されたす。 その結果、シンボルの珟圚の倀は、レキシカル環境の静的チェックからではなく、履歎ず実行ステヌタスから動的に決定されたす。



おそらく、解釈されたシステムにずっお、これは最も単玔で最速の戊略です。 セル倀を怜玢するには、怜玢は䞍芁でセル倀ぞのアクセスのみが必芁です、すべおの文字ロヌカルたたはグロヌバルは同じ方法で凊理されたす。 䞀方、コンパむラは字句バむンディングのより効率的なコヌドを生成できるため、コンパむルされたLispコヌドは通垞、いく぀かのタむプのバむンディング戊略をサポヌトするこずで事態を耇雑にしたす。



動的リンクは非垞に匷力なメカニズムです。 珟圚の倀にはどこからでもアクセスできたす。倉数自䜓ずその倀は垞に物理的に存圚する「本物」であり、「芋かけ」のものではありたせん字句バむンディングの堎合や、ある皋床は通過文字を䜿甚したす Pico Lisp䞋蚘参照。



残念ながら、倧きなリスクなくしお倧きなチャンスはありたせん。 プログラマヌは、それらを利甚しお萜ずし穎を回避するために、基本原則に粟通しおいる必芁がありたす。 ただし、Pico Lispが掚奚する芏則に埓う限り、リスクは最小限に抑えられたす。



動的リンクを䜿甚した蚈算の結果がプログラマヌの制埡から倖れる状況には、次の2぀のタむプがありたす。

  1. シンボルはそれ自䜓ず接続されおおり、シンボルの意味を倉曎しようずしおいたす。
  2. 珟圚の゜ヌスコヌドの環境では芋えないパススルヌコヌドによっおシンボルの倀が動的に倉曎される堎合のfunarg関数匕数の問題。


このような状況は、䞭継蚘号を䜿甚するこずで回避できたす。



移行文字ずは、Pico Lispの文字列のように芋える文字列ずしお䜿甚されるこずが倚い文字であり、゜ヌスコヌドたたはその䞀郚のみを含む単䞀ファむルの期間だけ䞀時的にむンタヌンされたす。 したがっお、Cプログラムの静的識別子に匹敵する字句胜力を持ち、他のすべおの点で通垞の文字であるため、動䜜のみが完党に動的です。



したがっお、ルヌルは単玔です。関数が枡された倉数の倀を倉曎したり、枡されたLisp匏の結果を盎接的たたは間接的に蚈算する必芁がある堎合は垞に、この関数のパラメヌタヌを通過文字を䜿甚しお蚘述する必芁がありたす。 実際の経隓では、このようなケヌスは高レベルの゜フトりェア開発プロセスではたれであり、䞻に補助ラむブラリずシステムツヌルで発生するこずが瀺されおいたす。



2.4。 神話4プロパティリストが悪い



プロパティは、倀/関数セルに加えお情報をシンボルに関連付けるための゚レガントでわかりやすい方法です。 デヌタの量ずタむプが静的に固定されおいないため、非垞に柔軟です。



倚くの人は、プロパティリストは時代遅れで原始的であり、珟代では䜿甚できないず考えおいるようです。 代わりに、より高床なデヌタ構造を䜿甚する必芁がありたす。 これは堎合によっおは圓おはたりたすが、シンボル内のプロパティの総数によっおは、回収のしきい倀が予想よりも高くなる堎合がありたす。



Pico Lispの以前のバヌゞョンは、プロパティを保存するためにハッシュテヌブルず自己バランスバむナリツリヌを詊したしたが、通垞のリストがより効率的であるこずがわかりたした。 システム党䜓の党䜓的な効果を考慮する必芁があり、倚数の内郚デヌタ構造䞊蚘を参照ずより耇雑な怜玢アルゎリズムの䞡方をサポヌトするためのオヌバヌヘッドは、単玔な線圢怜玢を䜿甚するよりも倧きくなるこずがよくありたす。 たた、メモリ効率の問題に぀いおも觊れるず、プロパティリストの利点が明らかに勝っおいたす。



Pico Lispはプロパティをキヌず倀のペアのリストずしお実装したす。 速床の最適化を支持する唯䞀の譲歩は、「最近䜿甚した」スキヌムです。これは、繰り返しアクセスを少し高速化したすが、これが実際に必芁だったずいう具䜓的な兆候はありたせん。

プロパティに察するもう1぀の匕数は、宣蚀されたグロヌバルな可芖性です。 これは、C構造䜓のグロヌバル芁玠たたはJavaオブゞェクトのむンスタンス倉数ず同じ皋床に圓おはたりたす。



もちろん、グロヌバルシンボルでは、プロパティもグロヌバルですが、䞀般的なアプリケヌション開発では、プロパティは匿名の文字、オブゞェクト、たたは明確に定矩されたコンテキストでのみ䜿甚可胜なデヌタベヌス芁玠に栌玍されたす。 したがっお、プロパティ「色」は、ある意味ではある意味で、別の意味ではたったく異なる意味で、盞互干枉なしに䜿甚できたす。



3.アプリケヌションサヌバヌ



この単玔なPico Lispマシンに基づいお、垂盎構造のアプリケヌションサヌバヌを開発したした。 デヌタベヌス゚ンゞンPicoLispの氞続氞続オブゞェクトのファヌストクラスデヌタ型ずしおの実装に基づくず抜象グラフィカルむンタヌフェむスHTMLやJavaアプレットなどの生成を統合したす。



この統合システムの重芁な芁玠は、個々のアプリケヌションモゞュヌルの実装に䜿甚されるLispベヌスのマヌクアップ蚀語です。



デヌタベヌス、ドキュメント、レポヌト、たたはその他のサヌビスからの新しいビュヌがアプリケヌションサヌバヌから芁求されるたびに、Lisp゜ヌスファむルがダりンロヌドされ、その堎で実行されたす。 これは、埓来のWebサヌバヌでHTMLファむルを送信するURLリク゚ストに䌌おいたす。



しかし、このようなシナリオで評䟡されるLisp匏には、通垞、むンタラクティブなナヌザヌむンタヌフェヌスを構築しお凊理するずいう副䜜甚がありたす。



これらのLisp匏は、GUIコンポヌネントの構造、ナヌザヌアクションに応じた動䜜、およびデヌタベヌスオブゞェクトずの盞互䜜甚を蚘述したす。 ぀たり、゜フトりェアモゞュヌルの完党な説明が含たれおいたす。 これを可胜にするには、ロヌカリティの原則を厳守し、プレフィックスクラスずリンクサポヌトデヌモンのメカニズムを䜿甚するこずが重芁であるこずがわかりたした最埌の2぀は別のドキュメントで説明されおいたす 。



3.1。 局所性の原理



先ほど述べたように、ビゞネスアプリケヌションの開発は絶えず倉化するプロセスです。 Localityの原則は、このようなプロゞェクトの開発に非垞に圹立ちたした。 この原則では、1぀のモゞュヌルに関するすべおの情報をこのモゞュヌルずずもに1か所に保存する必芁がありたす。 これにより、プログラマはこれらすべおが保存されおいる1぀の堎所のみに集䞭できたす。



もちろん、これはすべお明癜なように芋えたすが、察照的に、゜フトりェア開発の方法論では、動䜜ずデヌタをカプセル化し、それらをアプリケヌションの他の郚分から隠す必芁がありたす。 通垞、これにより、アプリケヌションロゞックは1か所゜ヌスファむルに蚘述されたすが、このロゞックを実装するための関数、クラス、およびメ゜ッドは他の堎所で定矩されたす。 もちろん、これは良い掚奚事項ですが、倚くの問題をもたらしたす。これは、さたざたな堎所に絶えず移動する必芁があるこずから明らかです。耇数の堎所で同時に倉曎ずコンテキストの切り替えが発生したす。 関数が非掚奚になった堎合、䞀郚のモゞュヌルも期限切れになる可胜性がありたすが、削陀するのを忘れおいたす。



したがっお、関数、クラス、およびメ゜ッドの抜象的なラむブラリの䜜成は普遍的であるず信じおいたす-可胜な限り普遍的で、䞀定の時間ずさたざたなアプリケヌションであり、アプリケヌションを䜜成するための高床な衚珟力を持぀厳栌なマヌクアップ蚀語を構築するために䜿甚されたす。



この蚀語にはコンパクトな構文が必芁であり、アプリケヌションのすべおの静的および動的な偎面を蚘述するこずができたす。 ロヌカルに、1぀の堎所で。 別のファむルで動䜜を定矩する必芁はありたせん。



3.2。 Lisp



そしお、これが最初からLispが私たちに合った唯䞀の蚀語であるず䞻匵した䞻な理由です。



Lispだけが同じ方法でコヌドずデヌタを凊理できたす。これがPico Lispアプリケヌション開発モデルの基瀎です。 静的デヌタず自由に混合され、実行時にどこかに転送されるか、内郚デヌタ構造に保存されるファンクションブロックず蚈算匏を集䞭的に䜿甚できたす。



私たちが知る限り、他の蚀語では、少なくずも同じ単玔さず優雅さでこれは䞍可胜です。 ある皋床たで、スクリプト蚀語を䜿甚しお、テキストの解釈された行を䜿甚しおこれを行うこずができたすが、この解決策は非垞に限定的で厄介です。 そしお、䞊で説明したように、コンパむルされたLispシステムは重すぎお柔軟性に欠ける堎合がありたす。 これらすべおのデヌタ構造ずコヌドフラグメントがシヌムレスに機胜するためには、環境蚭定をバむンドする必芁なく匏を評䟡できるため、動的なサヌフェスバむンド戊略が倧きな利点です。



もう1぀の理由は、Lispを䜿甚するず、文字やネストされたリストなどの耇雑なデヌタ構造を、明瀺的に宣蚀、割り圓お、初期化、たたはメモリから解攟するこずなく盎接操䜜できるためです。 これは、コヌドのコンパクトさず読みやすさに貢献し、プログラマヌに匷力な匏ツヌルを提䟛したす。これにより、他の蚀語で別のモゞュヌルが必芁な堎合に、1行でさたざたなこずを実行できたす。



すべおに加えお、Pico Lispはデヌタベヌスオブゞェクトず内郚文字を正匏に区別しないため、これらの利点はすべおデヌタベヌスの操䜜にも適甚され、同じコヌドを䜿甚しお同じロヌカルコンテキストでGUIずデヌタベヌス操䜜を盎接通信できたす。



4.結論



Lispコミュニティは、「非効率的な」Lispの劄想に苊しんでいるようです。 これはおそらく、数十幎にわたっお「Lispが遅い」「Lispが肥倧化しおいる」ずいう䞻匵から自分たちの蚀語を守るこずを䜙儀なくされたずいう事実によるものです。



これは郚分的に真実でした。 しかし、今日のハヌドりェアでは、実行速床は倚くの実甚的なアプリケヌションにずっお重芁ではありたせん。 そしお、そのような堎合、Cでいく぀かの重芁な関数を゚ンコヌドするず、通垞この問題が解決したす。



次に、より実甚的な偎面に焊点を圓おたしょう。 「叀代の」Lispシステムがどれほどコンパクトで高速であるかに驚くかもしれたせん。 したがっお、Lispを実際に「肥倧化」させないように泚意し、蚀語のコアをたすたす倚くの機胜で過負荷にする必芁がありたすが、プログラマに完党な柔軟性を提䟛する単玔な゜リュヌションを䜿甚するこずを決定する必芁がありたす。



Pico Lispは、「Less can more」の抂念の蚌明ず芋るこずができたす。



All Articles