世界を動かす技術を、日本語で。

コードのフォーマットは不要であるべきだ

概要

  • コードフォーマット問題 は1980年代に既に解決されていた事実
  • Ada開発環境Rational R1000 の先進的機能紹介
  • DIANA IR によるテキストソース非保存方式
  • 現在でも フォーマット論争が続く現状 への疑問提起
  • 参考文献リンクとさらなる考察

コードフォーマット問題の歴史とAdaの先進性

  • コードフォーマット に関する議論は、実は 1980年代 に既に解決済みの課題
  • 高校時代の Mr. Paige (Adaコンパイラ開発経験者)による指摘
  • Ada開発環境 では、テキストソースを保存せず DIANA(Descriptive Intermediate Attributed Notation for Ada) という中間表現を利用
  • 各開発者が 好みの整形設定 でコード閲覧可能な仕組み
  • Rational R1000 ワークステーションの特徴
    • インクリメンタルコンパイル
    • セマンティック解析
    • バージョン管理
    • 統合デバッグ機能
  • Xerox Alto のようなワークステーションだが、Smalltalkではなく Ada を利用

DIANAとR1000の革新性

  • R1000 ではテキストソースを保存せず、 DIANA 形式でプログラムを管理
  • コンパイラとIDE がDIANAを直接理解し、任意の整形で表示可能
  • スペースとタブ による整形の違いが無意味化
  • プログラムツリー直接編集 (現代でいう projectional editing
  • Grady Booch による要約
    • 「R1000は事実上DIANAマシンだった。ソースコードはDIANAツリーの整形表示に過ぎなかった」
  • フォーマット論争やlinter問題 が発生しない開発環境

DIANA利用の追加メリット

  • ハードウェアアクセラレーション によるDIANA処理
  • インクリメンタルコンパイル (強い型付け言語では当時画期的)
  • 容易なリファクタリング ("refactoring"という言葉が生まれる前)
  • 高速な統合 (大規模Adaシステム開発に必須)

現代との比較と課題意識

  • 現在では ハードウェアアクセラレーション は不要、 リファクタリングツール も進化
  • しかし フォーマット問題 ではむしろ後退
  • projectional editing やライブ環境の普及は進まず
  • 現代の開発パラダイム に合った新しい解決策の模索が必要

参考文献・さらなる情報

  • Experiences with Code Generation (1985)
    • https://www2.eecs.berkeley.edu/Pubs/TechRpts/1985/CSD-85-249.pdf
  • Ada Compiler Validation Summary Report: Rational Environment (1985)
    • https://apps.dtic.mil/sti/tr/pdf/ADA157830.pdf
  • Grady Booch’s blog post about the 5th anniversary on Rational's acquisition (2008)
    • https://web.archive.org/web/20160304051102/https://www.ibm.com/developerworks/community/blogs/gradybooch/entry/rational_anniversary?lang=en#pagePlaceBar

Hackerたちの意見

ここでのトレードオフは、ソースファイルとやり取りするためのユニバーサルなツールセットが使えないことだね。テキスト以外のものだと、grepやdiff、sed、バージョン管理があまり効果的じゃなくなる。結局、専門的なツールやフォーマット、IDEの拡張に縛られちゃうんだよね。一方で、Unixの哲学はプレーンテキストとの組み合わせを重視してる。フォーマットの議論を切り裂くハサミがあるとしたら、もし選んだエディタで初期のスペース幅が設定できたら、タブを好む人たちは他に何か言い訳があるのかな?

OS全体がこれらのソースファイルを中心に構築されてるんだよね。一方で、Unixの哲学は「プレーンテキスト」を解析するコードが組み込まれたツールが設計されて初めて「繁栄」するんだ。

その通り。こういうアイデアは何度も出てくるけど、コストと利益が全然合わないんだよね。シンプルなフォーマッターを使うのを避けるために、信じられないほど複雑なツールを追加してるだけだし。全ての開発者が自分の好みでコードを見れることなんて、そんなに重要じゃないと思う。私が関わったチームでは、標準のスタイルガイドを使って、フォーマッターで強制してるけど、全員が全てのルールに同意するわけじゃない。それでも、慣れちゃうんだよね。コードのフォーマットについて議論したりこだわったりするのは、単なる無駄なバイクシェディングだと思う。

もし共通の中間エンコーディングがテキストで、バイナリじゃなかったらどうなる?そうすればgrepやdiff、sedはまだ使えるよね。ASTに基づいて動作するフォーマッティングツールがあれば、チェックインされたコードは特定のASTのための標準的な形式にできる。エディタはASTを解析して、ユーザーの選択した異なるフォーマットでソースを表示し、ファイルをディスクに書き込むときに標準形式に変換できるんだ。

DIANA irから元のソースコードみたいな形に戻すことってできるの?その逆変換の結果をgrepしたりできるし…

ソースを標準フォーマットで保存して、各開発者に合わせて unpack するなら…なんで標準フォーマットが普通のソースコードでなきゃいけないの?全てのツールはテキストバックエンドでも存在できるし、grepやsedのサポートもタダでついてくるよ!

もし初期のスペース幅が好きなエディタで設定できるなら、タブを好む人たちは他に何か意見があるのかな?もちろんあるよ。だってタブ幅は動的に柔軟だから、初期のスペース幅だけじゃ足りないんだ。

Grepやdiff、sed、行ベースの非セマンティックマージは、コードを操作するにはひどいツールだよ… それらでさらに深みにハマるより、何かもっと良いものを考える理由があった方がいいかもね。

これが機能するイメージは、gitフィルターみたいな感じだね。バージョン管理からチェックアウトすると、好みのフォーマットでテキストに変換されて、それを期待通りに扱うことができる。ステージングすると、保存された表現に変換される。gitでは、これはsmudgeとcleanフィルターを使って行われる、git LFSのようにね。フォージやその類のためのビューアもあって、必要に応じて保存された表現を解釈するように作られてる。テキストで作業するけど、そのテキストは標準の保存表現じゃない。構造が変わった時だけdiffが出てくる。事前コミットのリンターフックでもほとんど同じメリットが得られるけどね。

テキスト以外のものは、grepやdiff、sed、バージョン管理をあまり効果的にしないよね。UNIXの設計ミスかもしれないけど、テキストにこだわりすぎてる気がする。

テキストは確かに重要なポイントだけど、私たちが短期的な視野で谷に入ることを避けているせいで、ローカルな問題にハマっていると思う。あなたの例は構造的な知識があるコードに対してはうまく機能するよね:- grep: シンボル検索(テキストのgrepより100倍使ってる)や https://github.com/ast-grep/ast-grep - diff: https://semanticdiff.com(他にもいろいろ)、つまり:ノイズの多い構文の変更を隠して、移動したコードを捉えようとする。投影プログラミングがあれば、コードが移動することの表現力がもっと高くなると思う。- sed: https://npmjs.com/package/@codemod/cli - バージョン管理:Unisonのような言語を見て、ここでできる面白いことを探るのがいいと思う。特にライブラリに関しては。一般的な例としては、非意味的な変更(順序の変更や無関係な空白など)による競合がないこと。

面白い読み物だね。なんで表示されるものが保存されたアーティファクトと同じである必要があるのか、ずっと疑問に思ってた。git diffみたいなものも、ソースのIRのプロジェクションを通して見れるべきだと思う。treesitterみたいなものがあると、ASTやIRのための効率的で効果的なHCIがどうなるか、夢想することもあるよ。f#の順序付きコンパイルみたいなものは、コードレビューを簡単にしてくれるけど、それは中間形式の一部(依存関係の順序)が一級のアイテムとして見えるからなんだ。もっと緩い順序要件のコードの小さな変更を考えるよりも、ずっとシンプルに感じるよ。そういう場合、diffや関連するインターフェース、抽象クラス、実装を行ったり来たりして、デルタがプログラム全体にどんな影響を与えているのか理解するのが大変なんだ。

問題は「プレーンテキスト」以上の抽象的なものに投資できないってことだと思う。試みると、構文のプレーンテキストプロジェクションに格下げされちゃう。プレーンテキストエンコーディング自体は、モールス信号からユニコードに至るまでの段階的で経路依存的な開発の過程に存在していて、「巨大なルックアップテーブル」(GLUT、私が名付けた)アプローチによる記号の理解が進んでる。特定のビットパターンが常に特定のシンボルであることを知っていると、多くの機能が「ただ動く」って前提が役立つんだ。抽象レベルを上げると、アプリにより適した別のシンボルのセットが得られるけど、GLUTツールとは同等ではないんだ。代わりに、プレーンテキストの解析が輸送手段として使われることが多い。例えば、CSVの解析。これは雑だけど、十分に機能するんだ。追記:XMLも重要な例だね。テキスト輸送アプローチを尊重するためにわざわざ工夫されてる。専用のXMLエディタもあるけど、人々はプレーンテキストとして編集したいと思ってるのに、文字エンコーディングの問題でうまくいかない。編集したいシンボルにたくさんのアンパサンドやセミコロンが付いちゃうからね。だから「ハイパーテキストドキュメントのCSV」としてMarkdownが生まれたんだ。

ソースコードのフォーマットにはタイポグラフィの要素もあるよね。全てのコードフォーマットが単なる個人の好みだなんてことはない。特定の方法でコードをフォーマットすることで、意味や構造を伝えるのに役立つんだ。最小限のトークンがシリアライズされ、自動ツールで再構成されると、その意味が失われちゃう。

その例にはあまり納得できないな。> 私たちの中には、他のコードの部分を揃える人もいるし、繰り返しのインラインコメントもそうだよね。> さて、引数のブロックは三列のテーブルを形成してる。修飾子が第一列、データ型が第二列、名前が第三列に揃ってる。これって、コードフォーマットでカバーできるかなり些細なルーチンに感じる。forループみたいなもっと極端な例を考えることもできるけど、そんな超カスタムフォーマット(「組版」)は、いつも私を気まずくさせるし、みんなが好き勝手なフォーマットを使う理由を与えちゃう気がする。著者には意図があるけど、一貫性のないコードにぶつかると、変動が情報的でも役立つわけでもない。単に面倒で、疲れるだけだよ。保存されているものはおそらくもっとミニマルで、何らかの参照エンコーディング、もしかしたらjs用の見栄えを良くするものかもしれない。この文章の本質は、そんなことはどうでもいいってことだと思う。IDEは自分の好きなように表示・編集できるべきだよね。> みんなが自分の好きなように見るためのプリティプリント設定を持ってたんだ。

そうなんだよね!みんなそれが見えないのが信じられない。

Cの引数宣言は修飾子(register, const)、データ型(char )、名前(from)で構成されてるんだ。じゃあ「char argv[]」みたいな宣言を説明してみて… > それに加えて、データ型のスペースをcharとの間に入れないように再設定したんだ。この2つの変数のデータ型は「charへのポインタ」だから、引数名の前にスペースを置く方が理にかなってるよね(追記:これは単一の宣言にだけ意味があるってことは指摘しておくべきだね。char a, bみたいな構文は、charへのポインタaと通常のchar bを作ることになる)。ああ、そうだ、妄想的なC++のフォーマットスタイルね。少なくとも、更新でそれを避ける理由が説明されてるのは良いことだね。

そうだね。Pythonでは、blackフォーマッターがSQLAlchemyのクエリを読みにくい形で常に壊しちゃう(例えば、条件を必要以上に複数行に分けて、読みにくくする)。

それに、タイポグラファーはテーブルや数式を整えるために、全てを揃えて適切な間隔を保つために本当に努力してるんだよね。何世紀も手作業でやってきたのは、それが重要だから。外部の人には気づかれないことも多いけどね。(とはいえ、ソースコード用のもっと洗練されたフォーマッターを作ることもできるはず。)

タイポグラフィに気を使うのはいいけど、疑わしいプログラミング言語の慣習に盲目的に従うのは、本当に間違ったスタート地点に努力を注いでいるように感じる。そんなに意図を隠すことに意味があるの?最初の例を見てみよう。char * strcpy(to, from) register char *to; register const char *from; { char *save = to; for (; (*to = *from) != 0; ++from, ++to); return(save); } "長ったらしい" registerが許されるなら、なぜ全単語で文字を使わないの?それとも、もっと短いものが欲しいなら、signの方が一般的に意味的に合ってるよね。ポインタを設計するのに星を使うのはどうなの?sign-pointerにしてもいいし、もっとストレートなメタファーを使うならpinでもいい。ああ、ちなみに「ドット」(.)や「ダッシュ、グレーターザン」(->)を使うのは、タイポグラフィ的に全く意味がないよ。charはsign-pin-pinと比べて可読性を何ももたらさない。ほとんどの人は言葉や言葉の連なりを全体として読むからね。charをsign-pin-back-5と比べてみよう。strcpyはどうする?この文字列の山をデコードできることで賢く見せようとするの?string·copyやstringcopy(photocopyと比較して)でいいじゃん。あるいは単にcopyでも。冗長な識別子を避けたいなら、英語には同義語が豊富にあるよ。例えばduplicate、replicate、reproduce。さまざまな括弧は、適切なタイポグラフィがすでに整っているなら、オプションにしてもいいし、英語にはそれを置き換えたり補完したりできる副詞や前置詞がたくさんある。前置詞について言えば、物事を名詞で表現する方が適切なのに、fromやtoを識別子として使うのは本当に混乱を招く選択だよね。origin/sourceやdestination/targetの方がいいじゃん。識別子は興味の主なポイントなのに、その宣言文の最後に置くのはちょっと逆効果だよね。代入のための=も、←や≔のようなもっと関連性のある記号のアーティファクトに過ぎない。ほとんどのキーボードレイアウトはひどいデザインから来てるから。もっと適切な記号を使うことは、本当に不必要に曖昧な表記を推進することになる。文を終えるための必須セミコロンも、明らかにタイポグラフィ的に意味がないよ。forでパラメータを空白にするなら、何かを強調する方法よりも、別の制御フロー構文の方が明らかに良いと思う。すべてをまとめると:duplicateを関数として ⟨ requiring ( origin as sign-pin-register, destination as sign-pin-register ) making { save as sign-pin save assigned origin destination-pin assigned origin-pin until ( zeroized, whilst [ origin-increment, destination-increment wrought ] done ) return save made } built ⟩ こういう場合、括弧やコンマは純粋に装飾的なもので、コンパイラはそれらを無視しても十分な情報を持つことができる。例えば、duplicateを関数として requiring origin as sign-pin-register destination as sign-pin-register making save as sign-pin save assigned origin destination-pin assigned origin-pin until zeroized whilst origin-increment destination-increment wrought done return save made built とか、あるいは duplicateを関数として requiring origin as sign-pin-register destination as sign-pin-register making save as sign-pin save assigned origin destination-pin assigned origin-pin until zeroized whilst origin-increment destination-increment wrought done return save made built でもいい。

理論上は、人間が自動フォーマッターよりも良い仕事をすることができるけど、実際には全然そうじゃないから、その主張は無意味だね。

なんでみんなリンターの設定にそんなにこだわるのか、全然理解できない。明らかに無駄な議論だし、選んで自動でリンターを実行すればそれで終わりじゃん。実際のソフトウェアエンジニアリングに忙しくて、どこに何があるかなんて気にしてられないよ。1週間もすれば、チームが決めたフォーマットに慣れるって保証するよ。

一般的には同意だけど、行の最大長が高すぎてコードを読むときに横スクロールしなきゃいけないのは、生産性にすごく悪影響だよ。

なんでまだコードのプレーンテキスト表現を見てるのか、全然理解できないんだよね。もっと理にかなったコードの可視化があればいいのに。私の考えでは、この可視化は自動生成されたものじゃなくて、他の人に理解してもらいたいと思っている人間が愛情を込めて作ったものなんだ。これは典型的なデザイン文書とは違って、コードの一部としてメタデータに保存されている。変数や関数の命名の延長と考えてもらえればいいよ。もちろん「リテラルプログラミング」もあるけど、なぜかそれが大きなシステムで広がらなかったんだよね。[1] https://en.wikipedia.org/wiki/Literate_programming

なんで人々がリンターの設定にそんなにこだわるのか、全然理解できない。ソースコードフォーマットプログラムは、リンタープログラムとは違うんだ。前者は、出力がレイアウトルールに従うようにソースコードファイルを書き換えるけど、既存のロジックは変更しない。後者は、通常、正しい構文の中で潜在的な実装エラーを特定するために使われる冪等のソースコード分析プログラムの一種だ。いくつかの言語ツールはフォーマットとソースコード分析の両方をサポートしているけど、これは実装の詳細なんだ。0 - https://en.wikipedia.org/wiki/Lint_(software)

特定の保持オプションにはあんまりこだわってないけど(自分の好みが宇宙の中で最高だってのは確かだけど)、共通のリント設定がないと、毎回のPRでノイズが発生するのは避けたい。そう、gitもこれらのプログラミング言語も、アダのようにもっとエレガントに行を扱うべきなのに、ただのテキストとして扱うのは本当に馬鹿だと思う。20年以上のキャリアの中で、アダを使ったプロジェクトに提案されたのはたった一度だけ。エレガントで効率的なものを作るのは難しいし、世界的にトップクラスの存在感を持たせるのはもっと難しい。すでに良いものが揃っているエコロジカルニッチでは特にね。

一部の設定には利点があるよね。例えば、テーブルの末尾にカンマを付ける設定 [ 'apple', 'banana', 'orange', ] は、 [ 'apple', 'banana', 'orange' ] よりも利点がある。なぜなら、テーブルの最後に新しい行を追加する時、(1) 1行の編集で済むし、(2) コードレビューの差分が小さくて読みやすくなるから。だから、悪い選択は私の生活を難しくするんだ。同じことがローカル変数の宣言にも当てはまる。ソートされたリスト(またはソートされたインクルード)は、私の生活を楽にしてくれるものだよ。もしソートされていなかったら、みんなが新しいものを最後に追加することになるから、マージコンフリクトが何倍も増える。ソートされているからといってゼロになるわけじゃないけど、「最後に追加する」よりは少なくなる。だから、自動フォーマッターが時間を節約するためにあるように、可能な限りソートしないことで私の時間を無駄にしないでほしい。あと、私のOCDは不一致が大嫌いなんだ。[1, 2, 3] {a, b, c} はOKだけど、[ 1, 2, 3 ] [ a, b, c ] もOKだけど、[1, 2, 3] { a, b, c } はダメ。どちらでもいいから、スタイルは一つに決めて、二つにしないで!

でも(少なくとも長い間)、自動でリンターを実行する機能はなかったんだよね。Goのgofmtがそのアイデアを人々に植え付けるまでは。あの頃にはいくつかフォーマットツールはあったけど、jslintやeslintには結構ギャップがあって、残念ながらコードレビューでそれを指摘することが多かったんだ。振り返ると、ただの細かいことを言ってたなって思う。

それは明らかにバイクシェッドの話だと思うけど、自分でその質問に答えたんじゃない? ;-)

いいリンティングルールが設定されていれば、その通りだね。99%のケースで有効なエラーやコードの匂いを見つけるのに役立つルールや、正しいことがない場合の純粋なフォーマットルールが必要だよ。リンティングが問題になるのは、意見が強くて根拠が疑わしい場合で、問題を見つけるのを助けるどころか邪魔になる時だね。リンティングルールと戦う必要はないはずなのに、残念ながらそうなることが多いんだ。俺の他のコメントも見てみて: https://news.ycombinator.com/item?id=45166670

同意するよ。リンターは現代の開発で一番イライラする部分の一つだね。関係ないことなのに、マージする時にかなりの時間を取られちゃう。多くのエディタや言語の組み合わせは、初めから自動リンティングを提供してないし、もしあってもCIパイプラインが推測するルールとは違うことが多いと思うよ。

Rustがコラボレーションに向いている理由の一つは、意見がはっきりしているから、みんなが本当の問題解決に集中できることだね。ESLintやPrettierの設定について無駄に議論するのは、時間の使い方としてはあまり良くないと思う。

プロジェクショナルエディティングはテキストソースでもできるよ。これがJetBrains MPSがコードからテーブルをレンダリングしてる古い動画だよ。https://www.youtube.com/watch?v=XolJx4GfMmg&t=63s 辞書をテーブルとしてレンダリングできるIDEを期待してるんだけど、私の欲しいものリストはそれだけじゃないよ。現在、コード折りたたみやインレイヒント、HTMLとしてレンダリングされたドックストリングなどの機能がちらっと見えてるね。https://x.com/efortis/status/1922427544470438381

その前提には反対だな。コードのフォーマットは重要なコミュニケーション手段だよ。きちんとフォーマットされたコードは、次のことを示すべきなんだ:1. 開発者はフォーマットが大事だって理解するだけの経験がある。2. 開発者は選んだフォーマットルールを守るだけの規律がある。3. 開発者は良いフォーマットルールを選ぶためのセンスがある。4. 開発者は他の理由があればルールを一時的に破る判断力がある。これらは開発者にとって本当に重要な属性だよ。コードのあらゆる側面に影響を与えるから、フォーマットだけじゃないんだ。フォーマットはそれを測るための非常に迅速な指標に過ぎない。残念ながら、自動フォーマットやリンターのルールがその信号を壊してる。グッドハートの法則がまたもや発動だね。

フォーマットに無関心でいることは、私に次のことを示している:- おそらく1人以上の人が編集するコードベースで働いたことがない - ブランチ間でのマージをまともにやったことがない - 大きなコードベースを維持したことがない - 大きなコードベースをリファクタリングしたことがない - コードベースの履歴を読むためにdiff/比較ツールを使ったことがない - コードベースのためのツールを作ったことがない - チームプレイヤーとしては良くないし、自分のことだけにしか興味がない

ブログのエントリーは短くてシンプルだから、タイトルに反応する前に一度読んでみるといいよ。そうすれば「すべき」と「不必要」がそのタイトルでどういう意味を持つのか理解できるかもしれない。

特定のフォーマットでテキストを整えたい時ってあるよね。例えば、リストを視覚的にテーブルに変えたいとか。

もしその質問に対する答えが「絶対にノー」って状況なら、コードを保存・コミットする時に自動でフォーマットするツールを設定しちゃえばいいと思う。それに、誰かがそれをスキップしたらCIが文句を言うようにしておけば、もうそれでいいんじゃないかな。細かいことにこだわるより、デフォルトの設定のままでいいと思う。自分のスタイルを捨てて、みんなが使ってるツールでのリントやフォーマットに従った方が、コードを引き継ぐ人にとっても馴染みやすいしね。フォーマットとリントは違うけど、どちらかを設定したら、もう片方もやっちゃった方がいいかもね。

誰かのコードフォーマットって、シボレットみたいなものだと思う?フォーマッターやリントに関してどう感じてる?

同じ性格の特徴は、筆跡からもより良く評価できるから、これからは全てのPRを cursive で提出することを求めるつもりだよ。

望ましいソースコードのフォーマットは、抽象構文木だけからは導き出せないこともあるよね。例えば、次の(擬似)コードを考えてみて:bar.glob = 1; bar.plu.a1 = 21; bar.plu.coza = fol; このコードはこのようにフォーマットされるべき?それとも、三つの代入が行われていることを強調するために、bar.glob = 1; bar.plu.a1 = 21; bar.plu.coza = fol; のようにフォーマットされるべき?それとも、bar.glob = 1; bar.plu .a1 = 21; bar.plu .coza = fol; のように、構造体の「深さ」をよりタブularにして、どのメンバー変数がどの「深さ」にあるかをすぐに見えるようにするべき?さらに進んで、bar.glob = 1; bar.plu.a1 = 21; bar.plu.coza = fol; のように、著者が読者に数の大きさを簡単に理解してもらいたいと考えていることを強調することもできる(だから、ExcelやLibreOffice Calcでは、数値はデフォルトで右揃えになっている)。また、これを深さを「タブular」にすることと組み合わせると、bar.glob = 1; bar.plu .a1 = 21; bar.plu .coza = fol; になる。それぞれのフォーマットは、著者が強調したいコードの異なる側面を強調している。この情報は、単なる抽象構文木からは導き出せない。むしろ、プログラマーが意図した構造を「解釈」するためには、追加の情報が必要なんだ。

あなたの例の後半の2行は、LoD違反の匂いがするね。フォーマットの問題じゃなくて、構造の問題だよ。

でも「望ましいコードフォーマット」って主観的だよね。2スペース、4スペース、8スペースが好きな人もいれば、あなたが示したようなカラムレイアウトが好きな人もいるし。ASTだけからフォーマットを推測するのは無理だよ。ASTはソースコードじゃないし、フォーマット情報も持ってないから。

あなたの言いたいことはわかるけど、実際には最初の2つのフォーマットしか使ったことがないし、私の目標は常に可読性だったんだ。テキストの代わりにASTを保存するのは情報が失われるけど、得られるものより失うものが価値があるのかな?もしあなたの例が失う中で一番良いものなら、やっぱりそれでも大きな勝利だと思うよ。異なる部分を強調する方法もあって、ASTへの往復でも生き残るんだ。例えば、深さを強調する方法:setValue([bar, glob], 1) や setValue([bar, plu, a1], 21) あるいはデータを強調する方法:configure(bar, 1, 21, fol)。それに、もし本当にこのスタイルを維持したいなら、スタイルのオーバーライドを許可することもできるよ:// $formatblk: tabular_keypaths, aligned_assignments bar .glob = 1 bar .plu .a1 = 21 // $formatblk-end

ああ、eslint-config-airbnbね。俺が好きなairbnbの設定の問題はこれだよ: https://github.com/airbnb/javascript/issues/1271 https://github.com/airbnb/javascript/issues/1122 既存のプロジェクトをairbnbの設定に合わせるのに、1時間以上もかかっちゃった。コードは完璧に正しくて、分かりやすくて、メンテナンスもしやすかったのにね。結局、その特定のルールはローカルで無効にしたよ。他のプロジェクトでは使ったことないし。(どうやらそのプロジェクトはもうメンテされてないみたい。良かった良かった。)airbnbの設定は、俺の見解では、リンティングが下手に行われると人の生産性を無駄にする完璧な例だと思う。

約20〜25年前に、構文木を直接扱ってソースコードをその構文木の生成されたシリアライズとして扱う動きがあったんだ。これはリファクタリングから始まったと思うけど、90年代に先駆けていたね。Visual Ageみたいなものは、ファイルシステムではなくデータベースにコードを保存していたし、後に意図的プログラミング(チャールズ・シモニーが推進してた)もこれを試みていたよ。もちろん、モデル駆動開発も同じ頃にあったね。リファクタリング(正しく行われれば)は、参照整合性などを保つ構文木の変換なんだ。リファクタリングを適用する前後でコードが同じことをすることを保証するんだ。シンボルを直接扱っているなら、名前を変更するのは簡単になるよ。ファイルベースのソースツリーでこれを実現するには、全体をパースして、ファイル内でシンボルがどこで参照されているかを追跡し、シンボルの名前を変更して、ソースツリー内のすべての場所を更新する必要があるんだ。コードの表現がファイルの束ではなく構文木であれば、その作業はずっと楽になるよ。シンボルはただ違う名前になるだけだから。もちろん、人々はファイルを編集するのが好きで、それがより構造を保つツールを開発する際の摩擦を生んでいるんだ。四半世紀経ってもまだフォーマットの問題について議論しているのは、再考するべきことかもしれないね。多くの言語やエディタでは、堅牢なシンボルの名前変更はまだSFのようなものだし、これは最も基本的なリファクタリングに過ぎないんだ。