11

Google の新しい言語Goは、モジュールにリストされているすべての依存関係が実際に使用されることを明示的に要求することで、依存関係の管理を容易にしようとしています。コンパイラは、モジュールから何も使用せずにモジュールへの依存関係を宣言するモジュールを拒否します。

パッケージがそれ自体をインポートしたり、エクスポートされた識別子を参照せずにパッケージをインポートしたりすることは違法です。

明白な利点 (よりクリーンなモジュールなど) をいくつか思いつくことができますが、明らかでない利点もあるかもしれません。私が考えることができる唯一の欠点は、リファクタリング中に不平を言いすぎる、過度にペダンティックなコンパイラーを持っていることですが、おそらくもっとありますか?

これを強制する他の言語の経験はありますか? このアプローチの長所と短所は何ですか?

4

3 に答える 3

5

すべての依存関係を明示的に使用する必要があるだけでなく、すべての変数も使用する必要があります。未使用の変数があると、コンパイラはエラーを返します。

彼らは迷惑です。しかし、きれいなコードが得られるので、他の人を幸せにするでしょう。

おそらく Go の設計者は、Go を主に IDE に依存する言語にするつもりだったのではないかと考えています。

于 2009-12-01T11:43:19.537 に答える
1

これに対する最大の動機と最大の結果は、コンパイル時間の改善だと思います。テクニカル プレビュー ビデオでは、短期間に大量のコードをコンパイルする能力が強調されていました (彼らの例では、MacBook で 8 秒で 200,000 行のコードをコンパイルしました。マシンの仕様は示されていません)。

また、技術ビデオでは、彼らが達成した最大の方法の 1 つは、モジュールのコンパイルとリンクの方法を変更したことであると具体的に述べています。

現在の C/C++ システムで何かがどのように機能するかの例を次に示します。

クラス A はヘッダー ファイル C_H で定義され、C_CPP で実装されます。クラス B は C から派生し、ファイル B_H および B_CPP に実装されています。クラス A は B から派生し、ファイル A_H および A_CPP に実装されます。

派生チェーンのため、A_CPP には A_H、B_H、および C_H が含まれます。B_CPP には、B_H と C_H が含まれます。C_CPP には C_H が含まれます。基本的に #include をカット アンド ペースト操作に変える C プリプロセッサの性質により、C_H の内容はコンパイラで 3 回実行され、B_H は 2 回実行されます。

さらに、A_CPP、B_CPP、および C_CPP の内容はすべて、独自のオブジェクト ファイルに存在します。したがって、リンカが Ao を解決しようとすると、Bo と Co の両方をロードして処理する必要があります。また、Bo を解決するときは、Co を再度処理する必要があります。

プリコンパイル済みヘッダーは、この問題の最初の部分でかなり役立ちますが、維持するのが大変な場合もあり、その理由で単純にヘッダーを使用しない多くの開発者を知っています。また、問題が根本的に変わるわけではありません。ヘッダーは複数のレベルで複数回処理されますが、ソースの代わりにプリコンパイルされたバイナリが処理されるだけです。いくつかのステップが切り取られていますが、プロセス全体ではありません。

Go は異なる方法でアプローチします。彼らのテクニカルトークからのPDFからの直接の言葉で:

「Go コンパイラは、オブジェクト ファイルから推移的な依存関係の型情報を取得しますが、必要なものだけを取得します。A.go が B.go に依存している場合、C.go に依存している場合: - C.go、B.go、次に A.go をコンパイルします。 - A.go をコンパイルするために、コンパイラは Co ではなく Bo を読み取ります。大規模な場合、これは大幅なスピードアップになる可能性があります。"

OK、わずかな接線が完了しました。なぜそれが関連するのですか?答えは、Go Tech Talk PDF にもあります。

「パッケージ モデル: 高速なビルドを可能にする明示的な依存関係。」

Go 開発者は、非常に大規模なプロジェクトであっても、コンパイル時間が秒単位で測定される場合、開発者が維持する方が生産的であるというスタンスをとったと推測しています。短いコンパイル時間。200,000 行のコードをコンパイルし、無関係なパッケージのインポートがあることを発見するのに 8 秒かかり、それを見つけて修正するのに (優れた IDE または開発環境に精通している場合) 5 ~ 10 秒かかるとします。再コンパイルするのにさらに 8 秒かかります。これを合計 30 秒と呼びます。これで、今後のコンパイルはすべて 10 秒の範囲内にとどまります。または、不要な依存関係を含めてモジュールを成長させ、コンパイル時間が 8 秒から 10 秒、12 秒、または 15 秒に増加するのを監視することもできます。私たちは皆、時間を分単位でコンパイルすることに慣れているので、大したことではないように思えますが、それが 25% のパフォーマンス低下であることに気付き始めると、立ち止まって少し考えてみてください。

Go のコンパイル時間はすでに超高速です。また、プロセッサの速度は (以前ほどではないとしても) 依然として向上しており、利用可能なコアの数も増加していることも考慮してください (また、大量のコードをコンパイルすることはマルチスレッドに適しています)。今日、200,000 行のコードが 8 秒で処理されるということは、10 年後に 200,000 行のコードが実質的に瞬時にコンパイルされることを想像しても不合理ではないことを意味します。Go チームはここでコンパイル時間を過去のものにするという意識的な決定を下したと思います。あなたが提起した問題はそのほんの一部にすぎませんが、それまだその一部です。

まったく別のことですが、Go チームは、優れたプログラミング プラクティスを強制する言語設計の哲学も開発したようです。彼らの名誉のために、彼らは深刻なパフォーマンスの低下なしにそれを達成するために努力し、大部分は成功しました。[余談: 実際にパフォーマンスに影響を与えていると思いつくのは、ガベージ コレクションと強制的に初期化された変数の 2 つだけです。後者は、この時代ではかなり些細なことです。] . これはプログラミングの世界では古くからある議論であり、Go が好きか嫌いか、どちら側に傾倒したかは明らかです。

2 つの力が一緒になって彼らの決定に影響を与えたと思います。結局のところ、これは良い方法だと思いますが、「--strict」フラグなどを使用してこれを行うことを許可することを提案した他のコメンターを支持しますが、特にプロジェクトのライフサイクルの初期段階では、特定の動作はオプションです。後で必要になることがわかっているコードを最初に書き始めたとき、それらを必要とするコードをまだ書いていなくても、変数を定義したり、パッケージを含めたりしている自分を簡単に見ることができます。

于 2009-12-01T15:33:08.213 に答える
0

yuku が言ったように、Netbeans や Eclipse が Java に対してできることと同等の IDE を持っていれば、この種のことを気にする必要はありません。

余白にある小さな電球を右クリックし、[未使用の依存関係をすべて削除] を選択します。

使用されていない変数については、通常、波線の下線が引かれ、非常に簡単に見つけることができます。

ここでの唯一の違いは、他の言語とは異なり、実際には IDE に加えてコンパイラーが不平を言うことですが、IDE を使用する場合、これは問題になりません。

職場では、もちろん他の言語についても、とりわけ (自分たち自身で) 同じことをしなければならないと述べているコーディング ポリシーがあります。ですから、この種のこれには実際に実際のアプリケーションがあると言えます。私見ですが、コンパイラは開発者にこの動作のオンとオフを切り替えるオプションを提供する必要があります。厳密モードの誰か?

于 2009-12-01T12:16:16.880 に答える