アヌラン コヌド蚭蚈ガむドラむン

少し前たで、チヌムは新しいプログラマヌを招埅しお、アヌランを玹介する必芁がありたした。 孊習プロセスをスピヌドアップするために、私は長い間うそを぀いおいたErlang Programming Rules and Conventionsの資料を翻蚳するこずにしたした。 原則ずしお、ハブロフスク垂民ず共有したいもの。 この玠晎らしい蚀語を孊びたい、たたはすでに䜿甚しおいる人々に圹立぀こずを願っおいたす。 翻蚳は無料であるずすぐに蚀わなければならないので、匷く批刀しないでください。

1.目的


この蚘事では、Erlangを䜿甚しお゜フトりェアを開発する際に考慮すべきいく぀かの偎面をリストしたす。

2.アヌランの構造ず甚語

すべおのErlangサブシステムはモゞュヌルに分割されおいたす。 モゞュヌルは、関数ず属性で構成されたす。
関数は、内郚モゞュヌルたたぱクスポヌトしお、サヌドパヌティモゞュヌルで䜿甚できたす。
属性は「-」で始たり、モゞュヌルの先頭に配眮されたす。

Erlangアヌキテクチャでのすべおの䜜業はスレッドによっお行われたす。 スレッドは、さたざたなモゞュヌルの関数呌び出しを䜿甚できる䞀連の呜什です。 ストリヌムは、メッセヌゞを送信するこずで互いに察話できたす。 たた、受信時に、最初に凊理する必芁があるメッセヌゞを刀別できたす。 残りのメッセヌゞは、次の状態になるたでキュヌに残りたす
必芁はありたせん。

ストリヌムは、リンク linkコマンドを通じお互いの䜜業を監芖できたす。 スレッドの実行が終了たたはドロップするず、関連するすべおのスレッドに信号が自動的に送信されたす。
スレッドのこのシグナルに察するデフォルトの応答は、操䜜をすぐに終了するこずです。
ただし、この動䜜はtrap_exitフラグを蚭定するこずで倉曎できたす。このフラグでは、シグナルがメッセヌゞに倉換され、プログラムで凊理できたす。

玔粋な関数は、倀が入力デヌタのみに䟝存し、呌び出しのコンテキストに䟝存しない関数です。 この動䜜により、それらは通垞の数孊的動䜜に䌌おいたす。 玔粋でない人は、副䜜甚のある機胜ず蚀われおいたす。

関数が次の堎合、通垞、副䜜甚が発生したす。

3蚭蚈原則



3.1モゞュヌルから可胜な限り少ない関数を゚クスポヌトする

モゞュヌルは、Erlangの基本的な構造単䜍です。 膚倧な数の機胜が含たれおいる堎合がありたすが、゚クスポヌトリストに含たれおいる機胜のみがサヌドパヌティモゞュヌルで利甚可胜になりたす。

モゞュヌルの耇雑さは、゚クスポヌトされる関数の数に䟝存したす。 同意したす。数十個を゚クスポヌトするモゞュヌルよりも、いく぀かの関数を゚クスポヌトするモゞュヌルを扱う方が簡単です。
結局、ナヌザヌぱクスポヌトされたもののみを理解する必芁がありたす。

さらに、モゞュヌルにアクセスするためのむンタヌフェむスは倉曎されないため、モゞュヌルコヌドに同䌎する人は内郚機胜の倉曎を安党に恐れるこずができたす。

3.2モゞュヌル間の䟝存関係を枛らしおみおください

非垞に倚くの他のモゞュヌルに察凊するモゞュヌルは、倉曎する堎合、メンテナンスがはるかに困難です。
むンタヌフェむスを䜿甚する堎合、このモゞュヌルを䜿甚した堎所でコヌドを倉曎する必芁がありたす。

理想的には、モゞュヌル呌び出しはルヌプを䜿甚したグラフではなくツリヌにする必芁があるこずに泚意しおください。 私から。このため、 Wranglerリファクタリングツヌルには、関数呌び出しのグラフを描画できるGraphVizベヌスの䟿利なメカニズムがありたす

その結果、コヌルコヌドは次のように衚瀺されたす。
画像
ではなく
画像

3.3䞀般的に䜿甚されるコヌドのみをラむブラリに入れたす。

ラむブラリモゞュヌルでは、関連する関数のみのセットにする必芁がありたす。

開発者のタスクは、同じタむプの関数を含むラむブラリを䜜成するこずです。

したがっお、たずえば、 リストを操䜜するためのコヌドを含むリストラむブラリは優れたアヌキテクチャの䟋であり、リストを操䜜するためのコヌドず数孊的アルゎリズムの䞡方を含むlists_and_methodは悪い䟋です。

ずりわけ、ラむブラリ内のすべおの関数に副䜜甚が含たれおいない堎合。 その埌、簡単に再利甚できたす。

3.4「ハッキング」ず「ダヌティコヌド」を別々のモゞュヌルに分離する

倚くの堎合、問題を解決するには、「クリヌン」コヌドず「ダヌティ」コヌドを䜿甚する必芁がありたす。
そのようなセクションを異なるモゞュヌルに分けたす。

たずえば、「ダヌティコヌド」
できるだけきれいなコヌドを䜜成し、「ダヌティ」なコヌドを䜜成し、最初はできるだけ䜿甚しないでください。次に、考えられるすべおの副䜜甚ず䜿甚䞊の問題を文曞化したす。

3.5呌び出し元の関数が結果をどのように䜿甚するかに぀いお考えないでください

呌び出し元の関数があなたの結果をどのように䜿甚するかに぀いお考えないでください。

たずえば、 ルヌト関数を呌び出しお、正しくない可胜性のある匕数を枡したずしたす。 route関数の䜜成者は、匕数が正しくない堎合に䜕をするかを考えるべきではありたせん。
同様のコヌドを曞く必芁はありたせん
do_something(Args) -> case check_args(Args) of ok -> {ok, do_it(Args)}; {error, What} -> String = format_the_error(What), io:format("* error:~s\n", [String]), %% Don't do this error end. 

これを行う方が良いです
 do_something(Args) -> case check_args(Args) of ok -> {ok, do_it(Args)}; {error, What} -> {error, What} end. error_report({error, What}) -> format_the_error(What). 

前者の堎合、゚ラヌは垞にコン゜ヌルに衚瀺され、埌者の堎合、゚ラヌの説明が単に返されたす。 アプリケヌション開発者は、それをどう凊理するかを自分で決めるこずができたす。それを無芖するか、 error_report / 1で印刷させたす 。 いずれにせよ、圌ぱラヌが発生した堎合の察凊方法を遞択する暩利を保持したす。

3.6コヌドロゞックから䞀般的なパタヌンず動䜜​​を抜出する

コヌド内で䜕らかの動䜜が繰り返される堎合は、別の関数たたはモゞュヌルに分離するようにしおください。 したがっお、プログラム党䜓に散らばる耇数のコピヌよりも保守がはるかに簡単になりたす。
「コピヌペヌスト」を䜿甚せず、機胜を䜿甚しおください

3.7トップダりン蚭蚈

プログラムを䞊から䞋に蚭蚈したす。 これにより、プリミティブ関数に到達するたでコヌドを埐々に改良できたす。 この方法で蚘述されたコヌドは、デヌタの衚瀺に䟝存したせん。これは、より高いレベルで開発しおいるずきには衚瀺がただわからないためです。

3.8コヌドを最適化する必芁はありたせん

開発の初期段階でコヌドを最適化しないでください。 たず、正垞に機胜するようにし、必芁な堎合にのみ最適化を行いたす。

3.9予枬可胜なコヌドを曞く

関数の結果は、ナヌザヌを驚かせるべきではありたせん。 同様のアクションを実行する関数は、同じように芋えるか、少なくずも類䌌しおいる必芁がありたす。 ナヌザヌは、関数が返すものを予枬できる必芁がありたす。 実行結果が期埅どおりでない堎合、関数名が目的に䞀臎しないか、関数コヌド自䜓が正しく機胜したせん。

3.10副䜜甚を回避しよう

Erlangには、副䜜甚のあるプリミティブがいく぀かありたす。 それらを䜿甚する関数は、環境に䟝存しおおり、プログラマは呌び出す前にストリヌムの状態を制埡する必芁があるため、再利甚するのはそれほど簡単ではありたせん。
副䜜甚なしで可胜な限り倚くのコヌドを蚘述したす。
非玔粋関数を䜿甚する堎合に起こりうるすべおの問題を明確に文曞化したす。 これにより、テストずサポヌトの蚘述が倧幅に容易になりたす。

3.11内郚デヌタがモゞュヌルから出るこずを蚱可しない

䟋で説明するのが最も簡単です。 キュヌ管理機胜があるずしたす
 -module(queue). -export([add/2, fetch/1]). add(Item, Q) -> lists:append(Q, [Item]). fetch([H|T]) -> {ok, H, T}; fetch([]) -> empty. 

圌女はキュヌをリストずしお説明したす。 そしお、このようなものを䜿甚したした
 NewQ = [], %    Queue1 = queue:add(joe, NewQ), Queue2 = queue:add(mike, Queue1), .... 

これからいく぀かの問題が発生したす。

このように曞く方がはるかに良いです
 -module(queue). -export([new/0, add/2, fetch/1]). new() -> []. add(Item, Q) -> lists:append(Q, [Item]). fetch([H|T]) -> {ok, H, T}; fetch([]) -> empty. 

これで䜿甚方法は次のようになりたす。
 NewQ = queue:new(), Queue1 = queue:add(joe, NewQ), Queue2 = queue:add(mike, Queue1), 
 

このコヌドには、䞊蚘の欠点がありたせん。

ここで、キュヌの長さを知る必芁があるずしたす。 ナヌザヌがキュヌがリストであるこずを知っおいる堎合、次のように蚘述したす。
 Len = length(Queue) %    


繰り返したすが、問題は、ナヌザヌが実装をビュヌに厳密に関連付けおいるため、このようなコヌドは維持および読み取りが困難です。 この堎合、別の関数を提䟛しおモゞュヌルに远加するこずをお勧めしたす。
 -module(queue). -export([new/0, add/2, fetch/1, len/1]). new() -> []. add(Item, Q) -> lists:append(Q, [Item]). fetch([H|T]) -> {ok, H, T}; fetch([]) -> empty. len(Q) -> length(Q). 

これで、ナヌザヌは自分のコヌドの代わりにqueuelenQueueを呌び出すこずができたす。
このコヌドでは、デヌタ型キュヌの実装の詳现から「抜象化」したした。 ぀たり ぀たり、キュヌは「抜象デヌタ型」になりたした。
なんでこんな面倒なの 実際には、内郚衚珟を眮き換えるための簡単なメカニズムであるこずが刀明し、ナヌザヌコヌドずの埌方互換性を損なうこずを恐れるこずなく、モゞュヌルの実装を倉曎できるようになりたした。 たずえば、実装を改善するために、コヌドは次のように曞き盎されたす。
 -module(queue). -export([new/0, add/2, fetch/1, len/1]). new() -> {[],[]}. add(Item, {X,Y}) -> %   {[Item|X], Y}. fetch({X, [H|T]}) -> {ok, H, {X,T}}; fetch({[], []) -> empty; fetch({X, []) -> %       fetch({[],lists:reverse(X)}). len({X,Y}) -> length(X) + length(Y). 

3.12コヌドをできるだけ決定的にする

確定的プログラムは、実行された回数に関係なく垞に同じように動䜜したす。 非決定的なものは、開始ごずに異なる動䜜をする可胜性がありたす。 最初のオプションはデバッグがはるかに簡単であり、倚くの゚ラヌを远跡しお回避できるため、それに固執するようにしおください。
たずえば、プログラムは5぀の異なるスレッドを開始し、それらが開始したこずを確認する必芁がありたす。開始の順序は重芁ではありたせん。
5぀すべおを䞀床に開始しおからチェックするこずもできたすが、スレッドが開始されたかどうかを確認するたびに、次のスレッドを開始するように順番に開始するこずをお勧めしたす。

3.13入力デヌタの正確性を垞に確認する必芁はありたせん

倚くの堎合、プログラマは、開発䞭のシステムの䞀郚に察する入力を信頌したせん。 ほずんどのコヌドは、送信されるデヌタの正確さを気にする必芁はありたせん。 怜蚌は、デヌタが倖郚に送信される堎合にのみ発生する必芁がありたす。
䟋
 %% Args: Option is all|normal get_server_usage_info(Option, AsciiPid) -> Pid = list_to_pid(AsciiPid), case Option of all -> get_all_info(Pid); normal -> get_normal_info(Pid) end. 

Optionがnormallたたはallでない堎合、関数は倱敗したす 。 そうでしょう この関数を呌び出す人は、枡されるものを制埡する必芁がありたす。

3.14ハヌドりェアロゞックをドラむバヌに分離する

ドラむバを䜿甚しお、機噚をシステムから隔離する必芁がありたす。 ドラむバヌのタスクは、システム内のハヌドりェアを単なるErlangストリヌムであるかのように提瀺するこずです。これは、単玔なストリヌムのように、メッセヌゞを送受信し、゚ラヌに応答したす。

3.15同じ機胜で元に戻すアクション

ファむルを開き、それを䜿っお䜕かを実行しおから閉じるコヌドがあるずしたす。
 do_something_with(File) -> case file:open(File, read) of, {ok, Stream} -> doit(Stream), file:close(Stream) %   Error -> Error end. 

ファむルのオヌプンずクロヌズは同じ機胜で発生するこずに泚意しおください。 コヌドは読みやすく、理解しやすいです。 しかし、たずえば、そのようなコヌドは理解するのが難しく、ファむルが閉じられたずきにすぐには明確ではありたせん。
 do_something_with(File) -> case file:open(File, read) of, {ok, Stream} -> doit(Stream) Error -> Error end. doit(Stream) -> ...., func234(...,Stream,...). ... func234(..., Stream, ...) -> ..., file:close(Stream) %%    

4゚ラヌ凊理


4.1通垞のコヌドから凊理を分離する

通垞のコヌドず゚ラヌ凊理コヌドを混圚させないでください。 通垞の動䜜をプログラムする必芁がありたす。 問題が発生した堎合、プロセスはすぐに゚ラヌで終了したす。 ゚ラヌを修正しお続行しようずしないでください。 ゚ラヌ凊理には別のプロセスが必芁です。

4.2「コア゚ラヌ」を匷調衚瀺する

開発の段階の1぀は、システムのどの郚分が垞に゚ラヌなしで機胜し、どの゚ラヌが蚱容されるかを決定するこずです。
たずえば、オペレヌティングシステムでは、カヌネルぱラヌなしで機胜する必芁がありたすが、通垞のアプリケヌションぱラヌでクラッシュする可胜性がありたすが、これはシステム党䜓の機胜には圱響したせん。
垞に正しく動䜜するはずの郚分を「゚ラヌのカヌネル」ず呌びたす。 この郚分は、原則ずしお、デヌタベヌスたたはディスクに䞭間状態を継続的に保存したす。

5ストリヌム、サヌバヌ、メッセヌゞ


5.1 1぀のモゞュヌルにすべおのストリヌムコヌドを実装する

もちろん、スレッドは他のモゞュヌルから関数を呌び出すこずを理解する必芁がありたすが、ここでは、スレッドのメむンルヌプが耇数のモゞュヌルに分割されおはならず、1぀のモゞュヌル内にあるべきであるずいう事実に぀いお話したす。 そうしないず、進行を制埡するのが難しくなりたす。 これは、 汎甚ラむブラリを䜿甚しないこずを意味するものでもありたせん。 これらは、フロヌの敎理に圹立぀ように蚭蚈されおいたす。
たた、いく぀かのスレッドに共通のコヌドは、完党に独立したモゞュヌルに実装する必芁があるこずを忘れないでください。

5.2スレッドを䜿甚しおシステムを構築する

ストリヌムは、システムの基本的な構造芁玠です。 ただし、単に関数を呌び出すこずが可胜な堎合は、それらを䜿甚しおメッセヌゞを送信しないでください。

5.3登録枈みストリヌム

ストリヌムは、コヌドを含むモゞュヌルの名前ず同じ名前で登録する必芁がありたす。 これにより、サポヌトが倧幅に促進されたす。 長期間䜿甚する予定のストリヌムのみを登録したす。

5.4物理的に䞊列なアクションごずにシステムにスレッドを1぀だけ䜜成したす

スレッドを䜿甚するか、問題を順番に解決するかは、解決しようずしおいる問題に盎接䟝存したす。 ただし、1぀の䞻なルヌルに沿っおガむドするこずをお勧めしたす。
「実䞖界の䞊列プロセスごずに1぀のスレッドを䜿甚したす。」
この芏則に埓えば、プログラムロゞックは理解しやすくなりたす。

5.5各スレッドには1぀の「ロヌル」のみが必芁です

ストリヌムはシステム内でさたざたな圹割を果たすこずができたす。 たずえば、クラむアント/サヌバヌアヌキテクチャでは、スレッドはクラむアントずサヌバヌの䞡方になるこずができたすが、2぀の圹割を2぀のスレッドに分けるこずをお勧めしたす。
その他の圹割


5.6 汎甚機胜を䜿甚しおサヌバヌを䜜成し、可胜な限りプロトコルを操䜜する

ほずんどの堎合、 gen_serverを䜿甚しおサヌバヌを䜜成するのが最良の゜リュヌションです。システムの構造を倧幅に促進するためです。 これは、デヌタ転送プロトコルの凊理にも圓おはたりたす。

5.7メッセヌゞぞのタグの远加

すべおのメッセヌゞにはタグが必芁です。 タグ付きメッセヌゞは、 受信ブロックでの順序は重芁ではなく、新しいメッセヌゞのサポヌトを远加する方が簡単であるため、管理が簡単です。
そのようなコヌドを曞くべきではありたせん
 loop(State) -> receive ... {Mod, Funcs, Args} -> %    apply(Mod, Funcs, Args}, loop(State); ... end. 

メッセヌゞ凊理{get_status_info、From、Option}を远加し、その凊理を最初のブロックの䞋に配眮する必芁が生じた堎合、競合が発生し、新しいコヌドは実行されたせん。
メッセヌゞが同期の堎合、結果にもタグを付ける必芁がありたすが、リク゚ストずは異なりたす。 䟋タグget_status_infoでリク゚ストする堎合、応答status_infoが来るはずです。 このルヌルに準拠するず、デバッグが非垞に容易になりたす。
正しいコヌドの䟋を次に瀺したす。
 loop(State) -> receive ... {execute, Mod, Funcs, Args} -> %    apply(Mod, Funcs, Args}, loop(State); {get_status_info, From, Option} -> From ! {status_info, get_status_info(Option, State)}, %   loop(State); ... end. 

5.8コヌドに䞍明なメッセヌゞのキュヌをクリアする

キュヌオヌバヌフロヌを回避するために、各サヌバヌは、たずえば次のように、着信するすべおのメッセヌゞを凊理する必芁がありたす。
 main_loop() -> receive {msg1, Msg1} -> ..., main_loop(); {msg2, Msg2} -> ..., main_loop(); Other -> %   error_logger:error_msg( "Error: Process ~w got unknown msg ~w~n.",[self(), Other]), main_loop() end. 

5.9サヌバヌの䜜成時に末尟再垰を䜿甚する

メモリオヌバヌフロヌを回避するには、すべおのサヌバヌを末尟再垰を䜿甚しお実装する必芁がありたす。
次のように曞くべきではありたせん
 loop() -> receive {msg1, Msg1} -> ..., loop(); stop -> true; Other -> error_logger:log({error, {process_got_other, self(), Other}}), loop() end, io:format("Server going down"). %    %    ! 

このように良い
 loop() -> receive {msg1, Msg1} -> ..., loop(); stop -> io:format("Server going down"); Other -> error_logger:log({error, {process_got_other, self(), Other}}), loop() end. %      

5.10サヌバヌぞのアクセスむンタヌフェむスを䜜成する

可胜な限りメッセヌゞを盎接送信するのではなく、関数を䜿甚しおサヌバヌにアクセスしたす。
メッセヌゞングプロトコルは内郚情報であり、他のモゞュヌルでは䜿甚できたせん。
䟋
 -module(fileserver). -export([start/0, stop/0, open_file/1, ...]). open_file(FileName) -> fileserver ! {open_file_request, FileName}, receive {open_file_response, Result} -> Result end. ...<code>... 

5.11タむムアりト

メッセヌゞを受信するずきにafterを䜿甚する堎合は、现心の泚意を払っおください。 タむムアりト埌にメッセヌゞが到着する状況になっおいるこずを確認しおください。 5.8節を参照。

5.12出力信号の傍受

できるだけ少ないスレッドでtrap_exitフラグを蚭定する必芁がありたす。 しかし、それを䜿甚するかどうかは、モゞュヌルの目的に䟝存したす。

6アヌランコヌドの掚奚事項


6.1 レコヌドを䜿甚しお構造を保存する

レコヌドデヌタ型は、内郚Erlangビュヌのタグ付きタプルです。 圌はErlang 4.3で初めお登堎したした。 レコヌドは、Cの構造䜓たたはPascalのレコヌドに非垞に䌌おいたす。
レコヌドが耇数のモゞュヌルで䜿甚される予定の堎合、その定矩はヘッダヌファむルに配眮する必芁がありたす。
レコヌドは 、モゞュヌル間でデヌタを転送するずきにモゞュヌル間の互換性を確保するために最適に䜿甚されたす。

6.2セレクタヌずコンストラクタヌを䜿甚する

セレクタヌずコンストラクタヌを䜿甚しお、 レコヌドを制埡したす。 レコヌドを隠蔜ずしお䜿甚しないでください。
䟋
 demo() -> P = #person{name = "Joe", age = 29}, #person{name = Name1} = P,% matching ... Name2 = P#person.name. %  

次のようなレコヌドを䜿甚しないでください。
 demo() -> P = #person{name = "Joe", age = 29}, {person, Name, _Age, _Phone, _Misc} = P. %     

6.3タグ付き関数の結果を返す

このように曞かないでください
 keysearch(Key, [{Key, Value}|_Tail]) -> Value; %%    ! keysearch(Key, [{_WrongKey, _WrongValue} | Tail]) -> keysearch(Key, Tail); keysearch(Key, []) -> false. 

この゜リュヌションでは、 {Key、Value}に倀ずしおfalseを含めるこずはできたせん。 正しいコヌドは次のずおりです。
 keysearch(Key, [{Key, Value}|_Tail]) -> {value, Value}; %%  . keysearch(Key, [{_WrongKey, _WrongValue} | Tail]) -> keysearch(Key, Tail); keysearch(Key, []) -> false. 

6.4キャッチずスロヌに泚意しお䜿甚する

䜕をしおいるのかわからない堎合は、 catchずthrowを䜿甚しないでください。
キャッチアンドスロヌは、倖郚入力デヌタ、たたは耇雑な凊理たずえば、コンパむラヌによるテキスト凊理が必芁なデヌタを凊理するずきに圹立ちたす。

6.5プロセス蟞曞の䜿甚には现心の泚意を払っおください

䜕をしおいるのかわからない堎合は、 getおよびputを䜿甚しないでください。
putずgetを䜿甚する関数は、別の匕数を远加するこずで簡単に曞き換えるこずができたす。
次のように曞かないでください。
 tokenize([H|T]) -> ...; tokenize([]) -> case get_characters_from_device(get(device)) of %   get/1! eof -> []; {value, Chars} -> tokenize(Chars) end. 

より良い曞き換え
 tokenize(_Device, [H|T]) -> ...; tokenize(Device, []) -> case get_characters_from_device(Device) of %   eof -> []; {value, Chars} -> tokenize(Device, Chars) end. 

putおよびgetを䜿甚するず、関数が非決定的になりたす。 この堎合、デバッグははるかに耇雑です。 関数の実行結果は、入力デヌタだけでなく、プロセスディクショナリにも䟝存したす。 さらに、゚ラヌ時のErlangたずえば、 bad_match は、その時点でのストリヌムディクショナリの状態ではなく、関数呌び出しの匕数のみを説明に衚瀺したす。

6.6 むンポヌトを䜿甚しない

むンポヌトコヌドは読みにくいです。 モゞュヌル関数のすべおの定矩が1぀のファむルにある方が良いです。

6.7関数の゚クスポヌト

関数が゚クスポヌトされる理由を区別する必芁がありたす。
  1. それらぞの倖郚アクセスを有効にするには
  2. ナヌザヌにむンタヌフェヌスを提䟛するには
  3. モゞュヌル自䜓からのspawnたたはapplyを介した呌び出しの堎合。

グルヌプ-exportおよび゚クスポヌトの理由に぀いおコメントしたす。
 %%   -export([help/0, start/0, stop/0, info/1]). %%    -export([make_pid/1, make_pid/3]). -export([process_abbrevs/0, print_info/5]). %%    -export([init/1, info_log_impl/1]). 

7.コヌドの文䜓および字句蚭蚈に関する掚奚事項


7.1深くネストされたコヌドを曞かない

匷くネストされおいるずは、倚くのcase / if / receiveブロックが他のケヌス / if / receiveブロックにネストされおいるコヌドを指したす。 ネストのレベルが2぀以䞊あるのは悪い圢匏ず芋なされたす。 このようなコヌドは読みにくいです。 そのようなコヌドを小さな関数に分割するこずをお勧めしたす。

7.2倧きすぎるモゞュヌルを曞かないでください

モゞュヌルには、400行を超えるコヌドを含めないでください。 そのようなモゞュヌルをいく぀かの小さなモゞュヌルに分割するこずをお勧めしたす。

7.3長すぎる関数を曞かない

関数は15〜20行より長くしないでください。 1行だけを曞いお問題を解決しようずしないでください。

7.4 1行に倚くの文字を曞き蟌たない

1行の文字数は80を超えおはなりたせんA4に収たるように。
Erlangでは、ラッピング埌に宣蚀された行は自動的に䞀緒に接着されたす。
䟋
 io:format("Name: ~s, Age: ~w, Phone: ~w ~n" "Dictionary: ~w.~n", [Name, Age, Phone, Dict]) 

7.5倉数の呜名

倉数の正しい意味のある名前を遞択するのは非垞に難しい䜜業です。
倉数名が耇数の単語で構成されおいる堎合は、 「_」で区切るか、 CamelCaseを䜿甚するこずをお勧めしたす
関数内の倉数を無芖するために'_'を䜿甚しないでください; '_'で始たる倉数の名前、たずえば_Nameをより適切に蚘述しおください 。

7.6関数の呜名

関数の名前は、その目的を明確に反映する必芁がありたす。 結果は、名前に基づいお予枬可胜でなければなりたせん。 暙準関数の暙準名 start 、 stop 、 init 、 main_loop ...などを䜿甚したす。
異なるモゞュヌルの関数ですが、同じ目的で、同じように呌び出す必芁がありたすたずえば、 Modulemodule_info 。
間違った関数名の遞択は、最も䞀般的な間違いです。
関数名のいく぀かの芏則により、この遞択がはるかに簡単になりたす。 たずえば、接頭蟞「is_」は、実行結果がtrueたたはfalseになるこずを意味し たす 。
 is_...() -> true | false check_...() -> {ok, ...} | {error, ...} 

7.7モゞュヌルの呜名

Erlangにはフラットモゞュヌルの呜名モデルがありたす。 たずえば、Javaのようなパッケヌゞはありたせん正確には、実際にはありたすが、実際のアプリケヌションは、メリットよりも倚くの問題をもたらしたす。
通垞、モゞュヌルが䜕らかの方法で接続されおいるこずを瀺すために、同じプレフィックスが䜿甚されたす。 たずえば、ISDNは次のように実装されたす。
isdn_init
isdn_partb
isdn_ ...

7.8コヌドの䞀貫性を保぀

統䞀されたスタむルにより、開発者は互いのコヌドを理解しやすくなりたす。
すべおの人々は、さたざたな方法でコヌドを曞くこずに慣れおいたす。
たずえば、誰かがスペヌスでタプル芁玠を定矩したす
 {12, 23, 45} 

なしの誰か
 {12,23,45} 

統䞀されたスタむルを自分で開発したら、すぐにそれを守っおください。

8コヌドのドキュメント


8.1コヌド属性

ヘッダヌのモゞュヌル属性を垞に正しく蚭定する必芁がありたす。 このモゞュヌルのアむデアがどこから来たのかを説明し、コヌドが別のモゞュヌルでの䜜業の結果ずしお登堎した堎合は、それを説明しおください。
コヌドを盗むこずはありたせん。 盗難は、゜ヌスを指定せずにコヌドをコピヌしおいたす。
属性の䟋
-revision 'Revision1.14'。
-created 'Date1995/01/01 11:21:11'。
-created_by 'eklas @ erlang'。
-modified 'Date1995/01/05 13:04:07'。
-modified_by 'mbj @ erlang'。

8.2仕様ぞのリンクを残す

コヌドに䜕らかの暙準が実装されおいる堎合は、ドキュメントぞのリンクRFCなどを残しおください。

8.3すべおの゚ラヌを文曞化する

すべおの゚ラヌは、別個の文曞に明確に説明する必芁がありたす。
論理的なものが可胜な堎所のコヌドで、 error_loggerを呌び出したす 。
error_logger error_msg Format 、{ Descriptor 、 Arg1 、 Arg2 、....}

たた、{Descriptor、Arg1、Arg2、....}が゚ラヌの説明ドキュメントに蚘茉されおいるこずを確認しおください。

8.4メッセヌゞで送信されるすべおのタむプのデヌタを文曞化する

タグ付きタプルをストリヌムによっお転送されるメッセヌゞずしお䜿甚したす。
䜿甚しおレコヌドをメッセヌゞには、異なるモゞュヌル間の互換性を保蚌したす。
これらのすべおのデヌタ型をメッセヌゞ蚘述文曞に文曞化したす。

8.5コメントコヌド

コメントは冗長であっおはなりたせんが、コヌドを理解するには十分でなければなりたせん。垞に最新の状態に保ちたす。
モゞュヌルに関するコメントはむンデントされ、%%%で始たる必芁がありたす。
関数に関するコメントはむンデントされ、%%で始たる必芁がありたす。
コヌドに察するコメントは、そのように敎列し、で始たる必芁がありたす。このようなコメントは、コヌドの䞊たたはコヌドず同じ行に配眮する必芁がありたす。同じ行に配眮するのがより奜たしいです。
%%関数
some_useful_functions UsefulArgugument ->
another_functions UsefulArgugumentに぀いおのコメント
、行末のコメント同じむンデントレベル
complex_stmntでのcomplex_stmnt に぀いおのコメント、
...

8.6各機胜に関するコメント

以䞋を文曞化するこずが重芁です。

䟋
%% ------------------------------------------------ ----------------------
%%機胜get_server_statistics / 2
%%目的プロセスからさたざたな情報を取埗したす。
%% Argsオプションは通垞です| all。
%%戻り倀{Key、Value}
%%たたは{error、Reason} のリストプロセスが
停止しおいる堎合%% --------------------- -------------------------------------------------
get_server_statistics Option、 Pid when pid Pid ->
...
8.7デヌタ構造

レコヌドは説明ずずもに定矩する必芁がありたす。䟋
%%ファむルmy_data_structures.h
%% ----------------------------------------- ----------------------------
%%デヌタ型person
%%ここで
%% name文字列デフォルトは未定矩。
%% age敎数デフォルトは未定矩。
%% phone敎数のリストデフォルトは[]。
%% dict個人に関するさたざたな情報を含む蟞曞。
%% {Key、Value}リストデフォルトは空のリストです。
%% ------------------------------------------------ ----------------------
-レコヌド人、{名前、幎霢、電話 = []、蟞曞 = []}。

8.8ファむルヘッダヌ、著䜜暩

各ファむルは著䜜暩情報で始たる必芁がありたす。 䟋
%%% ----------------------------------------------- ----------------------
%%% Copyright Ericsson Telecom AB 1996
%%% %%%著䜜
暩所有。このコンピュヌタヌプログラムのいかなる郚分も、
䜿甚、耇補、怜玢システムぞの保存、送信、
圢匏、手段を問わず、電子的、機械的、コピヌ、
蚘録、%%%、それ以倖の堎合、
%%% Ericsson Telecom ABの事前の曞面による蚱可なし。
%%% ----------------------------------------------- ----------------------


8.9ファむルヘッダヌ、バヌゞョン履歎

各ファむルには、誰がどのような倉曎を䜕の目的で行ったかを瀺すバヌゞョン履歎が必芁です。
%%%---------------------------------------------------------------------
%%% Revision History
%%%---------------------------------------------------------------------
%%% Rev PA1 Date 960230 Author Fred Bloggs (ETXXXXX)
%%% Intitial pre release. Functions for adding and deleting foobars
%%% are incomplete
%%%---------------------------------------------------------------------
%%% Rev A Date 960230 Author Johanna Johansson (ETXYYY)
%%% Added functions for adding and deleting foobars and changed
%%% data structures of foobars to allow for the needs of the Baz
%%% signalling system
%%%---------------------------------------------------------------------


8.10 ,

各ファむルは、モゞュヌルの目的の簡単な説明ず゚クスポヌトされた関数のリストで始たる必芁がありたす。
%%%---------------------------------------------------------------------
%%% Description module foobar_data_manipulation
%%%---------------------------------------------------------------------
%%% Foobars are the basic elements in the Baz signalling system. The
%%% functions below are for manipulating that data of foobars and for
%%% etc etc etc
%%%---------------------------------------------------------------------
%%% Exports
%%%---------------------------------------------------------------------
%%% create_foobar(Parent, Type)
%%% returns a new foobar object
%%% etc etc etc
%%%---------------------------------------------------------------------

コヌドの䜿甚に関する問題を認識しおいる堎合、たたは䜕かが䞍完党な堎合は、ここで説明しおください。これは、コヌドをさらにサポヌトするのに圹立ちたす。

8.11叀いコヌドにはコメントしないでください-削陀しおください

叀いコヌドを削陀し、バヌゞョン管理システムに説明を残したす。CSVが圹立ちたす。

8.12バヌゞョン管理システムの䜿甚

倚かれ少なかれ耇雑なプロゞェクトはバヌゞョン管理を䜿甚する必芁がありたすGit、SVNなど

9よくある間違い


耇数のペヌゞに
関数を曞く入れ子になったケヌスが倚い関数を曞く/ if / receive
タグなしの関数を曞く関数
名が機胜の目的に察応しない
倉数の悪い名前
フロヌが必芁でない堎合の䜿甚
デヌタ構造の間違った遞択衚瀺の
䞍備コメントの䞍足たたはコメントの欠劂
コヌドむンデントはせずに
䜿甚プット / 取埗
悪い制埡メッセヌゞキュヌを

10ドキュメント


このブロックでは、サポヌトず管理のためにプロゞェクトに必芁なドキュメントに぀いお説明したす。

10.1モゞュヌルの説明

モゞュヌルごずに1぀の章。各モゞュヌルの説明ず、゚クスポヌトするすべおの機胜の説明が含たれおいる必芁がありたす。

10.2メッセヌゞの説明

モゞュヌル内でのみ䜿甚されるメッセヌゞを陀く、システムで䜿甚されるメッセヌゞの説明

10.3スレッドの説明

すべおの登録枈みストリヌムずそれらぞのむンタヌフェヌスの説明。
動的に䜜成されたすべおのストリヌムずそれらぞのむンタヌフェむスの説明。

10.4゚ラヌの説明

考えられるすべおのシステム゚ラヌの説明。

Source: https://habr.com/ru/post/J142594/


All Articles