なぜ関数でbashスクリプト全体を書くのですか?

職場では、bashスクリプトを頻繁に作成しています。私の上司は、次の例のように、スクリプト全体を関数に分割することを提案しました。

#!/bin/bash # Configure variables declare_variables() { noun=geese count=three } # Announce something i_am_foo() { echo "I am foo" sleep 0.5 echo "hear me roar!" } # Tell a joke walk_into_bar() { echo "So these ${count} ${noun} walk into a bar..." } # Emulate a pendulum clock for a bit do_baz() { for i in {1..6}; do expr $i % 2 >/dev/null && echo "tick" || echo "tock" sleep 1 done } # Establish run order main() { declare_variables i_am_foo walk_into_bar do_baz } main 

「読みやすさ」以外にこれを行う理由はありますか。 、これは、コメントをいくつか追加し、行間隔を空けることで同様に確立できると思いますか?

スクリプトをより効率的に実行できますか(実際には逆のことを期待します)、それとも作成しますか?前述の読みやすさの可能性を超えてコードを変更する方が簡単ですか?それとも、それは本当に単なる文体の好みですか?

スクリプトはそれをうまく示していませんが、実際のスクリプトの関数の「実行順序」は非常に直線的である傾向があることに注意してください-walk_into_barは、i_am_fooが実行したものに依存し、do_baz

-したがって、実行順序を任意に交換できることは、私たちが通常行うことではありません。たとえば、突然declare_variableswalk_into_barの後に置きたくない場合は、問題が発生します。

上記のスクリプトの書き方の例は次のとおりです。

#!/bin/bash # Configure variables noun=geese count=three # Announce something echo "I am foo" sleep 0.5 echo "hear me roar!" # Tell a joke echo "So these ${count} ${noun} walk into a bar..." # Emulate a pendulum clock for a bit for i in {1..6}; do expr $i % 2 >/dev/null && echo "tick" || echo "tock" sleep 1 done 

コメント

  • 私はあなたが好きですボス。私のスクリプトでは、上部にmain()を配置し、下部にmain "$@"を追加して呼び出します。これにより、高値を確認できます。
  • 読みやすさは”いくつかのコメントと行間隔で同様に確立できるという考えに、私は同意しません。 。”おそらくフィクションを除いて、’ ‘ tには、各章とセクションの目次と説明的な名前があります。プログラミング言語では、’は、関数が提供できる読みやすさの種類です。 ndコメント’ can ‘ t。
  • 関数で宣言された変数はlocal-これは変数スコープを提供します。これは重要なスクリプトで非常に重要です。
  • 上司に同意しません。スクリプトを関数に分割する必要がある場合は、最初にシェルスクリプトを作成するべきではありません’。代わりにプログラムを作成してください。
  • 関数は、スクリプト内または複数のスクリプト内で繰り返されるプロセス用です。また、統一された方法論を導入することもできます。たとえば、関数を使用してsyslogに書き込みます。全員が同じ機能を使用している限り、syslogエントリの一貫性が高まります。あなたの例のような単回使用関数は、スクリプトを不必要に複雑にします。場合によっては、問題が発生します(変数のスコープ)。

回答

これと同じものを使い始めました KfirLaviのブログ投稿「DefensiveBashProgramming」を読んだ後のbashプログラミングのスタイル。彼はかなりの数の正当な理由を挙げていますが、個人的にはこれらが最も重要だと思います:

  • 手順は説明的になります:コードの特定の部分が何であるかを理解するのははるかに簡単ですコードの壁の代わりに、「ああ、find_log_errors関数がそのログファイルのエラーを読み取る」と表示されます。これをawk / grep / sed行全体を見つけることと比較してください。 use godは、長いスクリプトの途中でどのタイプのregexを知っているかを知っています。コメントがない限り、そこで何をしているのかわかりません。

  • 関数をデバッグできます。 set -xset +xで囲みます。コードの残りの部分が正常に機能することがわかったら、このトリックを使用して、その特定の関数のみのデバッグに集中できます。確かに、スクリプトの一部を囲むことはできますが、「長い部分である場合はどうなりますか?」次のようにする方が簡単です。

     set -x parse_process_list set +x 
  • cat <<- EOF . . . EOFを使用して使用法を印刷します。コードをよりプロフェッショナルにするために何度も使用しました。さらに、getopts関数を備えたparse_args()は非常に便利です。繰り返しになりますが、これは、すべてを巨大なテキストの壁としてスクリプトに押し込むのではなく、読みやすさに役立ちます。これらを再利用するのも便利です。

そして、明らかに、これははるかにC、Java、またはValaを知っているが、bashの経験が限られている人なら読むことができます。効率に関しては、できることはそれほど多くありません。bash自体は最も効率的な言語ではなく、速度と効率に関しては、perlとpythonを好む人がいます。ただし、nice関数を使用することはできます。

nice -10 resource_hungry_function 

コードのすべての行でniceを呼び出す場合と比較して、これにより、入力の量が減り、スクリプトの一部だけを低い優先度で実行したい場合に便利に使用できます。

私の意見では、関数をバックグラウンドで実行すると、全体を実行したい場合にも役立ちます。バックグラウンドで実行する一連のステートメント。

このスタイルを使用した例のいくつか:

コメント

  • その記事からの提案を真剣に受け止めるべきかどうかはわかりません。確かに、いくつかの良いアイデアがありますが、シェルスクリプトに慣れている人ではないことは明らかです。 single 変数は引用符で囲まれており(!)、UPPERCの使用を提案しています。 ASE変数名は、既存のenv変数と競合する可能性があるため、非常に悪い考えです。この回答のあなたのポイントは理にかなっていますが、リンクされた記事は、他の言語に慣れていて、自分のスタイルをバッシュに押し込もうとしている誰かによって書かれたようです。
  • @terdon記事に戻って、もう一度読みました。著者が大文字の変数の命名について言及しているのは、”不変のグローバル変数”だけです。グローバル変数を関数’の環境内にある必要がある変数と見なす場合は、それらを大文字にするのが理にかなっています。ちなみに、bash ‘のマニュアルには、変数の場合の’状態の規則がありません。 ここで受け入れられた回答でさえ”通常”と唯一の” div id = “b81bdbd960”>

標準”はGoogleによるものであり、’はIT業界全体を表すものではありません。

  • @terdon別のメモで、私は変数の引用が記事で言及されるべきであったことに100%同意します、そしてそれはブログのコメントでも指摘されています。また、’他の言語に慣れているかどうかに関係なく、このスタイルのコーディングを使用している人を’判断しません。この質問と回答全体は、’の利点と、’の程度を明確に示しています’他の言語に慣れていることはおそらくここでは関係ありません。
  • @terdonまあ、記事は”ソース

    マテリアル。すべてを自分の意見として投稿することもできましたが、記事から学んだことのいくつかと、これはすべて時間をかけて調査したことによるものであると認めなければなりませんでした。著者の’のリンクされたページは、LinuxとIT全般に優れた経験があることを示しているので、’この記事は’実際にはそれを示していませんが、Linuxとシェルスクリプトに関してはあなたの経験を信頼しているので、あなたは正しいかもしれません。

  • その’は優れた答えですが、’もBashの可変スコープがファンキーであることを追加したいと思います。そのため、localを使用して関数内で変数を宣言し、main()関数を介してすべてを呼び出すことを好みます。これにより、物事がはるかに管理しやすくなり、厄介な状況を回避できます。
  • 回答

    読みやすさは1つです。しかし、モジュール化にはこれだけではありません。 (半モジュール化は関数の方が正しいかもしれません。)

    関数では、いくつかの変数をローカルに保つことができます。これにより、信頼性が向上し、可能性が低くなります。物事が台無しになっています。

    関数のもう1つの利点は再利用性です。関数をコーディングすると、スクリプトで複数回適用できます。別のスクリプトに移植することもできます。

    コードは線形になる可能性がありますが、将来的にはマルチスレッドまたはマルチスレッドの領域に入る可能性があります。 Bashの世界での処理。関数で物事を行うことを学ぶと、並列へのステップの準備が整います。

    もう1つ追加するポイント。 Etsitpab Niolivが以下のコメントで気づいているように、「コヒーレントエンティティとしての関数からリダイレクトするのは簡単です。しかし、関数を使用したリダイレクトにはもう1つの側面があります。つまり、リダイレクトは関数定義に沿って設定できます。例:

    f () { echo something; } > log 

    これで、関数呼び出しによる明示的なリダイレクトは必要ありません。

    $ f 

    これにより、何度も繰り返す必要がなくなり、信頼性が向上し、物事を整理するのに役立ちます。

    関連項目

    コメント

    • とても良い関数に分割した方がはるかに良いでしょうが、答えてください。
    • 関数を追加すると、そのスクリプトを別のスクリプトにインポートできるようになります(sourceまたは. scriptname.sh、これらの関数を新しいスクリプトにあるかのように使用します。
    • その’はすでに説明されています別の回答で。
    • 感謝します。しかし、’他の人も重要視したいと思います。
    • 事件に直面しました。今日は、スクリプトの出力の一部をエコーではなくファイルにリダイレクトする必要がありました(電子メールで送信するため)。myFunction> myFileを使用して、目的の関数の出力をリダイレクトします。非常に便利です。関連性がある可能性があります。

    回答

    私のコメントでは、関数の3つの利点について説明しました。

    1. テストと正確性の検証が簡単です。

    2. 関数は将来のスクリプトで簡単に再利用(ソース)できます

    3. 上司はそれらを気に入っています。

    そして、3番目の重要性を過小評価しないでください。

    もう1つの問題に対処したいと思います:

    …したがって、実行順序を任意に交換できることは、私たちが通常行うことではありません。たとえば、突然declare_variableswalk_into_barの後に置きたくない場合は、問題が発生します。

    コードを関数に分割するメリットを得るには、関数をできるだけ独立させる必要があります。walk_into_barに次の変数が必要な場合が他の場所で使用されていない場合は、その変数をwalk_into_barで定義し、ローカルにする必要があります。コードを関数に分割し、それらの相互依存性を最小限に抑えるプロセスにより、コードがより明確でシンプルになります。 。

    理想的には、関数は個別に簡単にテストできる必要があります。相互作用のためにテストが簡単でない場合は、リファクタリングの恩恵を受ける可能性があることを示しています。

    コメント

    • I ‘ dは、’をモデル化するのが賢明な場合があると主張していますそして、それらの依存関係を強制するのに対して、それらを回避するためにリファクタリングします(enougがある場合からそれらのうちのh、およびそれらは’十分に毛深いので、物事が機能にまったくモジュール化されなくなった場合につながる可能性があります)。非常に複雑なユースケースは、かつてフレームワークにそれを実行するように促しました
    • 関数に分割する必要があるのは、例です。行き過ぎです。私を本当に悩ませているのは、変数宣言関数だけだと思います。グローバル変数、特に静的変数は、その目的専用のコメント付きセクションでグローバルに定義する必要があります。動的変数は、それらを使用および変更する関数に対してローカルである必要があります。
    • @Xalorous I ‘グローバル変数が初期化されるプロシージャ内で、外部ファイルから値を読み取るプロシージャを開発する前の中間的かつ迅速なステップとして…定義と初期化を分離する方がクリーンである必要があることに同意しますが、曲げる必要はほとんどありません。アドバンテージ番号3 ;-)

    回答

    完全に同意しますが再利用可能読みやすさ、上司への繊細なキスがありますが、 LDPが示すように

    #!/bin/bash # ex62.sh: Global and local variables inside a function. func () { local loc_var=23 # Declared as local variable. echo # Uses the "local" builtin. echo "\"loc_var\" in function = $loc_var" global_var=999 # Not declared as local. # Therefore, defaults to global. echo "\"global_var\" in function = $global_var" } func # Now, to see if local variable "loc_var" exists outside the function. echo echo "\"loc_var\" outside function = $loc_var" # $loc_var outside function = # No, $loc_var not visible globally. echo "\"global_var\" outside function = $global_var" # $global_var outside function = 999 # $global_var is visible globally. echo exit 0 # In contrast to C, a Bash variable declared inside a function #+ is local ONLY if declared as such. 

    これは現実の世界ではあまり見られませんシェルスクリプトですが、より複雑なスクリプトの場合は良い考えのようです。結合を減らすと、コードの別の部分で予期される変数を壊してしまうバグを回避できます。 。

    再利用性とは、多くの場合、関数の共通ライブラリを作成し、そのライブラリをすべてのスクリプトにsource組み込むことを意味します。これは、実行速度の向上には役立ちませんが、記述速度の向上には役立ちます。

    コメント

    • 明示的にlocalですが、関数に分割されたスクリプトを作成するほとんどの人は、依然として設計原則に従っていると思います。Usignlocalを使用すると、バグの導入が難しくなります。
    • localは、関数とその子で変数を使用できるようにするため、’渡すことができる変数があると非常に便利です。関数Aからダウンしていますが、関数Bでは使用できません。関数Bは、同じ名前で目的が異なる変数が必要な場合があります。そのため、’はスコープの定義に適しています。また、Vooが言ったように、バグが少なくなります

    回答

    C / C ++、python、perl、ruby、またはその他のプログラミング言語コードの場合と同じ理由で、コードを関数に分割します。より深い理由は抽象化です。低レベルのタスクを高レベルのプリミティブ(関数)にカプセル化して、処理方法を気にする必要がないようにします。同時に、コードがより読みやすく(そして保守しやすく)なり、プログラムロジックがより明確になります。

    ただし、コードを見ると、変数を宣言する関数があるのはかなり奇妙だと思います。これにより、私は本当に眉をひそめます。

    コメント

    • 過小評価された回答IMHO。main関数/メソッドで変数を宣言することをお勧めしますか?

    回答

    他の回答ですでに示した理由とはまったく異なる理由:この手法が時々使用される理由の1つは、トップレベルのnon-function-definitionステートメントは、mainの呼び出しであり、スクリプトが切り捨てられた場合に、スクリプトが誤って厄介なことを行わないようにするためのものです。スクリプトは切り捨てられる場合があります。もしそれがプロセスAからプロセスB(シェル)にパイプされ、プロセスAは、スクリプト全体の記述が完了する前に、何らかの理由で終了します。これは、プロセスAがリモートリソースからスクリプトをフェッチする場合に特に発生する可能性があります。セキュリティ上の理由から、これは良い考えではありませんが、実行されることであり、問題を予測するために一部のスクリプトが変更されています。

    コメント

    • おもしろい!しかし、私は、各プログラムでそれらのことを処理しなければならないのは厄介だと思います。一方、このmain()パターンは、ファイルの最後にif __name__ == '__main__': main()を使用するPythonでは通常です。
    • pythonイディオムには、mainを実行せずに他のスクリプトをimport現在のスクリプトにできるという利点があります。同様のガードをbashスクリプトに入れることができると思います。
    • @JakeCobbはい。私は今、すべての新しいbashスクリプトでそれを行っています。すべての新しいスクリプトで使用される関数のコアインフラストラクチャを含むスクリプトがあります。そのスクリプトは、ソースまたは実行できます。ソースの場合、その主な機能は実行されません。ソースと実行の検出は、BASH_SOURCEに実行中のスクリプトの名前が含まれているという事実を介して行われます。 ‘がコアスクリプトと同じである場合、スクリプトは実行されています。それ以外の場合は、’がソースになります。
    • この回答に密接に関連して、bashは、すでにディスク上にあるファイルから実行するときに、単純な行ベースの処理を使用します。スクリプトの実行中にファイルが変更された場合、行カウンターは’変更されず、’間違った行で続行されます。すべてを関数にカプセル化すると、’が実行前にすべてメモリに読み込まれるため、ファイルを変更しても’影響はありません。

    回答

    プログラミングに関連するいくつかの真実:

    • プログラムが変更されます。上司がそうではないと主張した場合でも、
    • コードと入力のみがプログラムの動作に影響します。
    • ネーミングは難しいです。

    コメントは、存在しないための一時的なギャップとして始まります。あなたのアイデアをコード*で明確に表現することができ、変化とともに悪化する(または単に間違っている)。したがって、可能であれば、概念、構造、推論、セマンティクス、フロー、エラー処理、およびコードをコードとして理解することに関連するその他のことを表現してください。

    とはいえ、 Bash関数には、ほとんどの言語には見られないいくつかの問題があります。

    • Bashでは名前空間がひどいです。たとえば、localキーワードの使用を忘れると、グローバル名前空間が汚染されます。
    • local foo="$(bar)"を使用すると 紛失 bar の終了コード。
    • ありません名前空間パラメータなので、さまざまなコンテキストで"$@"が何を意味するかを覚えておく必要があります。

    *これが問題になる場合は申し訳ありませんが、その後コメントを数年間使用し、コメントなしで**何年も開発することは、どちらが優れているかはかなり明確です。

    **ライセンス、APIドキュメントなどにコメントを使用することは依然として必要です。

    コメント

    • 関数の先頭でローカル変数をnullと宣言して、ほとんどすべてのローカル変数を設定しました。local foo=""次に、コマンド実行を使用して結果に基づいて動作するように設定します… foo="$(bar)" || { echo "bar() failed"; return 1; }。これにより、必要な値を設定できない場合に、すぐに機能を終了できます。 return 1が失敗した場合にのみ実行されるようにするには、中括弧が必要です。
    • 箇条書きについてコメントしたかっただけです。 ‘サブシェル関数’(中括弧ではなく括弧で区切られた関数)を使用する場合は、1)don ‘ローカルを使用する必要はありませんが、ローカルのメリットを享受できます。2)’

    (’ローカルを使用していないため)3)’心配する必要はありません誤ってグローバルスコープを汚染または変更した場合4)’という名前のパラメータ’を渡すことができます’ local ‘は、構文foo=bar baz=buz my-command

    回答

    プロセスにはシーケンスが必要です。ほとんどのタスクはシーケンシャルです。注文を台無しにするのは意味がありません。

    しかし、プログラミング(スクリプトを含む)の非常に重要なことはテストです。テスト、テスト、テスト。現在、スクリプトの正確さを検証するために必要なテストスクリプトは何ですか?

    上司は、スクリプトキディからプログラマーになるようにあなたを導こうとしています。これは進むべき良い方向です。あなたの後に来る人々はあなたを好きになるでしょう。

    しかし。プロセス指向のルーツを常に覚えておいてください。関数を通常実行される順序で順序付けることが理にかなっている場合は、少なくとも最初のパスとしてそれを実行します。

    後で、関数の一部が次のようになっていることがわかります。入力の処理、他の出力、他の処理、他のモデリングデータ、および他のデータ操作。したがって、同様のメソッドをグループ化して、別のファイルに移動することもできます。

    後で、 「スクリプトの多くで使用する小さなヘルパー関数のライブラリを作成したことに気付くでしょう。

    回答

    コメントまた、間隔は、関数が示す可読性に 近づくことはできません。関数がないと、木の森を見ることができません。大きな問題は、多くの詳細行の中に隠れています。言い換えれば、人々は細部と全体像に同時に焦点を合わせることができません。それは短いスクリプトでは明らかではないかもしれません。短いままである限り、十分に読みやすいかもしれません。ソフトウェアは大きくなりますが、小さくはなりません。 、そして確かにそれはあなたの会社のソフトウェアシステム全体の一部であり、確かに非常に大きく、おそらく数百万行です。

    次のような指示をしたかどうかを検討してください。

    Place your hands on your desk. Tense your arm muscles. Extend your knee and hip joints. Relax your arms. Move your arms backwards. Move your left leg backwards. Move your right leg backwards. (continue for 10,000 more lines) 

    途中、または5%を通過するまでに、最初のいくつかのステップが何であったかを忘れていたでしょう。木々の森が見えなかったので、ほとんどの問題を見つけることができなかったでしょう。関数と比較してください:

    stand_up(); walk_to(break_room); pour(coffee); walk_to(office); 

    行ごとのシーケンシャルバージョンにコメントをいくつ入れても、それは確かにはるかに理解しやすいです。また、はるかに、コーヒーを作るのを忘れていることに気付く可能性が高くなります。おそらく最後にsit_down()を忘れたでしょう。 grepとawkの正規表現の詳細を考えているとき、「全体像を考えることはできません。「コーヒーが作られていない場合はどうなりますか」」

    機能を使用すると、主に全体像を確認できます。コーヒーを作るのを忘れた(または誰かがお茶を好むかもしれない)ことに気づきます。別の時に、別の考え方で、詳細な実装について心配します。

    で説明されている他の利点もあります。もちろん、他の回答もあります。他の回答で明確に述べられていない別の利点は、機能がバグの防止と修正に重要な保証を提供することです。適切な関数walk_to()の変数$ fooが間違っていることに気付いた場合は、その関数の他の6行を調べるだけで、その問題の影響を受けた可能性のあるすべてのものと、可能性のあるすべてのものを見つけることができます。それが間違っている原因になっています。 (適切な)関数がないと、システム全体のすべてが$ fooが正しくない原因になる可能性があり、すべてが$ fooの影響を受ける可能性があります。したがって、プログラムのすべての行を再検討せずに$ fooを安全に修正することはできません。$ fooが関数に対してローカルである場合、その関数のみをチェックすることで、変更が安全で正しいことを保証できます。

    コメント

    • これは’ t bash構文ではありません。’は残念です。 ‘そのような関数に入力を渡す方法はないと思います。 (つまり、pour(); < coffee)。 c++またはphpのように見えます(私は思います)。
    • @ tjt263括弧なし、それ’のbash構文:コーヒーを注ぐ。 parensを使用すると、’は他のほとんどすべての言語になります。 🙂

    回答

    時は金なり

    他の良い答えがあり、スクリプトをモジュラー作成する技術的な理由に光を当てています。長く、作業環境で開発され、グループが自分の使用だけでなく使用するために開発されました。

    focus 1つの期待に焦点を当てる:作業環境では「時は金なり」。したがって、バグがないこととコードのパフォーマンスは、読みやすさ、テスト可能性、保守性、リファクタリング可能性、

    再利用性 …

    書き込み “モジュール “ コードを使用すると、コーダー自体だけでなく、テスターやテスターが使用する時間も短縮できます。ボス。さらに、上司の時間は通常、コーダーの時間よりも多く支払われ、上司があなたの仕事の質を評価することに注意してください。

    さらに独立した “modules” コード(bashスクリプトでも)を使用すると、 “並列” で作業できます。チームの他のコンポーネントは、全体的な制作時間を短縮し、せいぜいシングルの専門知識を使用して、他の部分に悪影響を与えずにパーツをレビューまたは書き直し、今書いたコードを「そのまま」リサイクルします。 / em>別のプログラム/スクリプトの場合、ライブラリ(またはスニペットのライブラリ)を作成するため、全体のサイズと関連するエラーの可能性を減らすため、各部分をデバッグおよびテストするため…そしてもちろん論理的に編成されますプログラム/スクリプトをセクション化し、読みやすさを向上させます。時間とお金を節約するすべてのもの。欠点は、標準に固執し、機能にコメントする必要があることです(作業環境で行うことはできません。

    標準に準拠すると、作業が遅くなります。最初はですが、その後は他のすべての人(そしてあなたも)の作業がスピードアップします。実際、コラボレーションに関与する人の数が増えると、これは避けられない必要性になります。したがって、たとえば、グローバル変数を関数ではなくグローバルに定義する必要があると思っていても、は常にmain()の最初の行で呼び出されます…

    最後になりましたが、最新のソースコードの可能性を過小評価しないでください選択的に分離されたルーチンを表示または非表示にするエディター( コード折り畳み )。これにより、コードがコンパクトになり、ユーザーが再び時間を節約できるようになります。

    ここに画像の説明を入力してください

    上記では、walk_into_bar()関数のみが展開されている様子を確認できます。他のものもそれぞれ1000行の長さでしたが、1つのページですべてのコードを制御し続けることができました。変数を宣言/初期化するセクションでも折りたたまれていることに注意してください。

    回答

    別の理由見落とされがちなのは、bashの構文解析です。

    set -eu echo "this shouldn"t run" { echo "this shouldn"t run either" 

    このスクリプトには明らかに構文エラーが含まれているため、bashで実行するべきではありません。間違っています。

    ~ $ bash t1.sh this shouldn"t run t1.sh: line 7: syntax error: unexpected end of file 

    コードを関数でラップした場合、これは発生しません:

    set -eu main() { echo "this shouldn"t run" { echo "this shouldn"t run either" } main 
    ~ $ bash t1.sh t1.sh: line 10: syntax error: unexpected end of file 

    回答

    他の回答に記載されている理由は別として:

    1. 心理学:コード行で生産性を測定しているプログラマーは、不必要に冗長なコードを書くインセンティブを持ちます。コード行に焦点を合わせると、プログラマーが不要な複雑さでコードを拡張しなければならないインセンティブが高まります。複雑さが増すと、メンテナンスのコストが増え、バグ修正に必要な労力が増える可能性があるため、これは望ましくありません。

    コメント

    • 反対票が言うように、それはそれほど悪い答えではありません。 注:agcによると、これも可能性があります。そうです。 彼は’それが唯一の可能性であるとは言いませんし、’誰も非難せず、事実を述べるだけです。 今日はほとんど聞いたことがないと思いますが、直接の”コード行”-> ” $$ “スタイルの契約ジョブは、間接的には非常に一般的であることを意味します。そうです、生成されたコードの質量はリーダーによってカウントされます。 / bosss。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です