独自の゜リュヌションの開発リスクず責任

こんにちは、Habr この蚘事では、Mail.Ru Groupでのコヌド䜜成のアプロヌチに぀いお説明したす。 既補の゜リュヌションを䜿甚する堎合、および自分で曞く方が良い堎合。 たあ、そしお最も重芁なこず-あなたの仕事が効果的でなく、他の人に利益をもたらさないようにするために、どのような措眮を講じる必芁があるか。 これらのニュアンスはすべお、内郚JSSDKを䜜成するタスクの䟋で考慮されたす。これは、2぀のプロゞェクトのコヌドベヌスを組み合わせる必芁があるために発生したした。





マむケル・パヌクスによるむラストレヌション



自転車を再発明するのは良くないず聞いおいたすが、自転車ず完成品の境界線はどこにあるのでしょうか Backbone 、 Ember、たたはAngular はどの段階でそうではなくなりたしたか これはめったに語られたせん。 過去4幎間、私はさたざたな皮類の「自転車」を継続的に開発しおきたした-私が奜きだからではなくしかし私は本圓に奜きです、䞀郚の゜リュヌションは時代遅れであり、他は特定の技術に結び付けられおいたすたずえば同じjQueryで これは必芁ありたせん。それを切り離すこずは、最初から曞くこずに盞圓したす。 しかし、䞻な問題は狭い専門性ず拡倧の機䌚の欠劂です。 同じgithubには倚くの決定がありたすが、誰もが未来を持っおいるわけではありたせん。 したがっお、あなたが考えおいるように、玠晎らしいこずを曞いお、タスクを緊急に完了するこずを決定した堎合、時間を無駄にせず、あなたの埌にそれをサポヌトしなければならない他の人に同情したす。 99の確率で、すべおを曞き換えたす。 それで、い぀自分の自転車を発明するこずが可胜であり、必芁なのでしょうか



タスクから始めお、それを評䟡したす



これらの単玔なポむントは、フレヌムワヌクたたはjQueryプラグむンの開発を問わず、ほがすべおのタスクに適甚できたす。



私たちの話は3幎前に始たりたした。タスクは「タッチデバむス甚のメヌルを開発する」こずでした。そのためには、すべおを行う必芁がある技術を遞択する必芁がありたした。 次の3぀のオプションがありたした。



  1. ビッグメヌルの経隓を掻甚したす。
  2. 人気のあるフレヌムワヌクを䜿甚したす。
  3. 自分で曞いおください。


ビッグメヌルのコヌドを䜿甚するこずはできたせんでした-17幎の歎史が自分を感じさせたす。 したがっお、自分で曞くか、既補のツヌルを探すかのいずれかでした。 このようなタスクのフレヌムワヌクを開発するこずは、私たちの経隓を考慮しおも非垞に困難です。これには実際には朜圚的な可胜性はありたせん。これは手抌し車に厳密に関連付けられた高床に専門化された゜リュヌションになる可胜性が非垞に高いです。 必芁なものを倧たかに想像しお、タスクおよび最も重芁なこずにはチヌムに適切な゜リュヌションを遞択したした。





これらのシンプルなツヌルにより、プロゞェクトを迅速に開発し、その実装を開始できたした。 タッチメヌルが倧きな機胜に远い付くたで、すべおがうたくいきたした。 このため、倚くの補品機胜は2回䜜成されたした。最初はメヌルで、次にtouch.mail.ruでしたが、実装の違いは最小限であり、構成に適しおいたした。 この状況は、新しいバック゚ンドAPIの導入によっお悪化したした。これは、答えを「プルしお取埗」するだけでは䞍十分でした。







これをすべお怜蚎した結果、もう二床ず開発、二重のバグ、二重のテスト、バグに陥るこずはできないず刀断したした。さらに、メヌル機胜の䞀郚を統合したい内郚プロゞェクトもありたす。



すべおが共通のコヌドベヌスの必芁性に぀いお蚀及したした。これは別のリポゞトリにあり、その䞭に共通のコンポヌネントが実装されたす。



プロゞェクトに関する知識を芁玄しお、基本的なパッケヌゞセットを決定したした。





そしお、それは䞭小䌁業です。これらのコンポヌネントを構築するものに぀いお





同様の質問に答えるために、私は自分で次の手順を策定したした。



  1. 既補の゜リュヌションのリストをコンパむルする完党に適切でない堎合でも。
  2. リストを調べたす玄1週間埌、コヌド、サポヌト、githubのタスクある堎合などを調べたす。
  3. ゜リュヌションがタスクに適合しない堎合、タスクを倉曎しようずしたすマネヌゞャヌ/デザむナヌに移動し、「これは䞍可胜です、すべおの愚か者」ではなく、代替手段を提䟛したす。
  4. あなたにふさわしくないものがあれば、準備はできおいたすか...埌で詳しく説明したす。




既補の゜リュヌションを芋぀ける



たず最初に、゜リュヌションの芁件を定矩するこずから始めたす。 これは、特定のタスクに必芁な機胜のリストその前に既に敎理枈みず拡匵性が必芁です。 過剰な゚ンゞニアリングに関䞎しないでください。それは良いこずには぀ながりたせんが、混乱させおタヌゲットから遠ざけるだけです。







そのため、最初にすべきこずは、モデルの䜜成方法に基づいお、モデルの凊理方法を決定するこずでした。 ただし、゜リュヌションには次の機胜が必芁であるこずを考慮する必芁がありたす。





前述したように、Backboneで構築された倚くのプロゞェクトず同様に、タッチメヌルは、Emitter、Model、Collection、Router、およびViewを提䟛する優れた基盀です。 これですべおのニヌズをカバヌできたす。



すべおがバックボヌンのない倧きなメヌルにのみかかっおいたしたが、同様のむンタヌフェヌスget / setを持っおいたモデルにありたした。



バックボヌン 郵䟿
䟝存関係 jQuery、Undescore jQuery
ドット衚蚘 - +
ゲッタヌ - +
キャッシング - -
モデルを保持 - +


ご芧のずおり、ビッグメヌルの基本機胜はBackboneにはないこずがわかりたした。 しかし バックボヌンは定評のある確立されたツヌルであり、巚倧なコミュニティず積極的なサポヌトがありたす。そのため、欠萜しおいる機胜のほずんどは、長い間曞かれテストされた拡匵機胜でカバヌできたす。



したがっお、ドット衚蚘は次を䜿甚しお取埗できたす。





ゲッタヌを実装するために、 https//github.com/asciidisco/Backbone.Mutatorsがありたす ただしgetのみ。



などなど。 残念ながら、私がどのように怜玢しおも、そのような機䌚がビッグメヌルの基瀎であったずき、私は箱から出しお「モデルの敎合性」をサポヌトする拡匵機胜を芋぀けるこずができたせんでした。



モデルの完党性ずは䜕ですか



手玙を受け取る䟋を考えおみたしょう。

function findOne(id) { var dfd = $.Deferred(); var model = new Backbone.Model({id: id}); model.fetch({ success: dfd.resolve, error: dfd.error }); return dfd.promise(); } // -   #1 findOne(123).then(function (model) { model.on("change:flag", function () { //   console.log(model.get("flag")); }); }); // - #2 findOne(123).then(function (model) { model.set("flag", true); //     });
      
      







䞀芋するず、たずえばfindOneメ゜ッドを倉曎しおプロミスを蚘憶し、それを返すこずで問題を修正できたす。

 var _promises = {}; //   //   function findOne(id) { if (_promises[id] === undefined) { var dfd = $.Deferred(); var model = new Backbone.Model({id: id}); model.fetch({ success: dfd.resolve, error: dfd.reject }); _promises[id] = dfd.promise(); } return _promises[id]; }
      
      







しかし、IDでモデルを怜玢するこずに加えお、モデルコレクションのリストもありたす。 たた、コレクションを取埗する堎所はどこでも、同じモデルのむンスタンスぞの参照で構成し、アプリケヌションの任意の時点で敎合性を維持する必芁がありたす。



もちろん、これはバックボヌンの䞊に巻き付けるこずができたすが、問題はこれだけではありたせん。 たずえば、コレクションメ゜ッドを実行した埌、出力で配列を取埗したす。

 //     id var ids = collection .where({ flag: true }) .pluck("id"); // TypeError: undefined is not a function
      
      







したがっお、Backboneで必芁なこずを行うには、次のものが必芁です。





必芁な機胜を実装する拡匵機胜を芋぀けたずしおも、このホッゞポッドで䜕かを構築するリスクはありたせん-これらの拡匵機胜の間でバグや競合が発生する可胜性が非垞に高く、重倧なパフォヌマンス障害が発生したす。 このような機胜は、フレヌムワヌク自䜓のコアに統合する必芁がありたす。



ロギングに぀いお少し
非垞に長い間、開発者が最初から最埌たでアクションを远跡するのに圹立぀高品質のログを取埗したいず考えおいたした。 ログの゚ントリに接続だけでなく、配列だけでなく、最も重芁なこずには、䞻芁な機胜のために、ロギングは「そのたた」動䜜するはずです



ロガヌは次のようになりたす。䟋を考えおみたしょう。

 //    Folder.find({limit: 50}).then(function (folders) { logger.add('folders', {length: folders.length}); //   «»     return folders.filter({type: Folder.TYPE_SMAP})[0].save({name: 'Bulk'}); });
      
      







そしおログ出力





ご芧のように、ログは入れ子になっおいるこずがわかりたした。さらに、各゚ントリはコヌド行に結び付けられおいるため、特別なコヌドを通じおコヌドのコンテキストでログを盎接監芖できたす。 むンタヌフェむスコヌドが瞮小されおいる堎合でも



rubaxa.github.io/Error.stack







さお、私たちは自分でモデルを曞きたす。 少なくずも残りのコンポヌネントの解決策を芋぀けおみたしょう。 たずえば、 Parse.comのように Backboneをフォヌクするこずもできたすし、私もそれを蚈画したしたが、倉曎の範囲はモデル自䜓のボリュヌムに匹敵したす。



Emterter



githubにアクセスしお「 Event Emitter 」を尋ねるず、次のラむブラリが芋぀かりたす。





オン/オフ/攟出 テスト handleEvent むベントオブゞェクト
EventEmitter2 + + - -
EventEmitter + + - -
マむクロむベント + - - -
jQuery + + - +


ご芧のように、それらはいずれもhandleEventやむベントオブゞェクトなどをサポヌトしおいたせん。たた、速床もあたり生産的ではありたせん。 ただし、䞀般的には適切であり、タヌンキヌ゜リュヌションずしお䜿甚できたす。



玄束





Q、い぀その他が玄束であるだけでなく、異なる機胜の銬車ず台車でもあり、玄束だけが必芁な堎合。 したがっお、Native + polyfilは、1぀の倧きなものではない堎合に理想的です。ただし、native promiseはjQueryず互換性がありたせんすべおこのコヌドのため。



リク゚スト



すべおが1぀に䌌おおり、たったくない゜リュヌションの無限の海を次に瀺したす。





最も近い適切なオプションはjQuery.ajaxのみです。



そのため、さたざたな理由で芋぀かった各゜リュヌションは、芁件に適合したせん。 䟋





もちろん、゜リュヌションの1぀を採甚し、機䌚を枛らしおjQueryに関䞎するこずができたした。 しかし、これらのモゞュヌルはそれほど倧きくなく、jQueryの存圚は期埅できたせんでした。



そしおその瞬間、ポむント4に戻りたすあなたに合ったものがなければ、準備はできおいたすか...



準備はいいですか...

  1. 狭い問題を解決するのではなく、䞀般的な解決策を曞きたす。
  2. テストずドキュメントを曞きたす。
  3. 7/24を維持したす。
  4. すべおを無料で行いたす。


最埌の点は誰かには奇劙に思えるかもしれたせんが、時間がかかりたす-これは実際に重芁な点です。 実際、あなたのフヌドの䞋にあるものをビゞネスするこずは重芁ではありたせん-それは利益を心配しおいたす私は珟圚䞀般的に蚀っおいたすので、あなたが䞻匵しお実装の時間を埗るこずができたなら、サポヌトはあなたの費甚で提䟛され、それは正盎です-それはですあなたの遞択、あなたの決定でした。 倚くの人がこの点を過小評䟡しおおり、そのために、GitHubが翌日にサポヌトが停止した決定で詰たっおいるようです。 愚かではない週に2、3のタスクそしお1日を準備する必芁がありたす。そしお、圌らがあなたに感謝する最倧倀は、すでに良いこずですそしお、それはテストでさえバグになるこずは別です。



だから、あなたはどこから始めるかを決めたすか 䞻なこずは、コヌディングするこずではありたせん プロゞェクトのむンフラストラクチャから始める必芁がありたす。



むンフラ



  1. うめき声たたは口論を構築したす。
  2. コヌドスタむル。
  3. テスト、カバレッゞ制埡、 CI 。
  4. JS、CS、TSたたはES6 / Babel。
  5. 倉曎管理の自動化。
  6. コヌドのドキュメントずドキュメント。
  7. 配垃方法github、bitbucketなど。


各項目は特定の問題を解決し、ナヌザヌが埓うルヌルの抂芁を瀺しおいるこずに泚意しおください。



私たちのために、私は次のスタックを遞択したした 



  1. プロゞェクトをビルドするGruntJS 。
  2. JSHintおよび.editconfig-コヌディングスタむルたたはタブ察に関するすべおの質問ず䜙分なホリバヌを削陀したす。 ロボットず議論するこずはできたせん。
  3. QUnit + Istanbul-テストは補品の品​​質を向䞊させるだけでなく、開発およびリファクタリングプロセスを加速したす。 カバレッゞは、テストがAPIにある機胜をどの皋床カバヌしおいるかを確認する機䌚を提䟛したす。 CIはTravisで 、珟圚はBambooです。
  4. ES5 + Polyphilsは最も重芁なポむントの1぀です。 TS 、 CS、たたはES6は単なるテクノロゞヌではありたせん。 この遞択は、゜リュヌションを別の開発者が䜿甚するかどうかの意思決定に倧きく圱響したす。
  5. git pre-commit-hookJSHint+ git pre-push-hookQUnit + Istanbul-package.jsonのpreinstallたたはpostinstallでフックをむンストヌルするなど、自動化できるものを自動化したす。
  6. JSDoc3-ドキュメントおよびコメントコヌド、最新のIDEはJSSDKに埓っおオヌトコンプリヌトを構築できたすが、最も重芁なこずは、コメントたたはパラメヌタヌの説明を読んだ埌、別の開発者がコヌドずそのロゞックにすばやく䟵入するこずです。




開発者は䜕から始めたすか



圌はgithubに行き、以䞋を芋たす







ご芧のずおり、プロゞェクトを䜿甚たたは開発する堎合に開発者が埓う必芁がある手順は、ここで説明されおいたす。



開発に盎接進みたす。



JSSDKでは、各モゞュヌルは4぀のファむルを含む個別のフォルダヌです。 たずえば、モデル



すでに曞いたように、自動化できるすべおのものを自動化したす。 したがっお、モゞュヌルを䜜成するために、個別の単調なタスクがありたす。



したがっお、たずえば、RPCModelを継承するmail.Folderモデルの䜜成は次のようになりたす。

 > grunt model:create:mail/Folder:RPCModel   «mail/Folder»..OK  «Folder»  boot.js .. OK JSSDK/mail/Folder/Folder.js .. OK JSSDK/mail/Folder/Folder.test.js .. OK JSSDK/mail/Folder/Folder.bench.js .. OK JSSDK/mail/Folder/README.md .. OK
      
      







開発䞭に、テストが最初に蚘述され、次にコヌドが蚘述されたす。 倉曎を行うか、新しいモゞュヌルを䜜成した埌、楜しい郚分が始たりたす-コミットずプッシュ







git commit -am"..."



- grunt jshint



開始しgrunt jshint





git push original master



- grunt test







タスクが倱敗するず、コミットたたはプッシュが倱敗したす。これにより、マスタヌ内のコヌドを垞に機胜させるこずができたす。 動䜜しないコヌドは、マスタヌ以倖のブランチでのみコミットできたす。 他のブランチでは、゚ラヌが衚瀺されるだけです。 たた、プッシュは匱いテストカバレッゞから抜け出せない堎合がありたす。 100未満の匱点珟圚1,635件のアサヌションをすべお考慮したす。



テストカバレッゞ



テストカバレッゞはすべおの病気の䞇胜薬ではありたせん。バグがないこずを100保蚌するものではありたせん。 カバレッゞが提䟛する䞻なものは、テストがすべおの可胜性にどの皋床圱響するかを評䟡する機胜です。たた、特定のコヌドの最終的な実装を再考できる堎合もありたす。



開発者はgrunt dev-server



し、次の図を芋たす







そしお、コヌド自䜓ずそのカバレッゞは次のずおりです。







ドキュメント



最埌の仕䞊げは、ドキュメントの生成です。 これを行うには、公匏のJSDoc3ずパブリッシャヌを䜿甚したす実際、npmはそのような゜リュヌションでいっぱいです。 最終的なドキュメントは2぀の圢匏で存圚したす。





これはREADME.mdモゞュヌルの倖芳です









ここでは、メ゜ッドの䟋ず説明、および䞍玔物ぞのリンクがすぐに衚瀺されたす。 各項目ぞのリンクを指定できたす。さらに、メ゜ッド名をクリックするず、コヌドにすばやくゞャンプできたす。



README.mdは、特別な劎力をかけずにどこからでも衚瀺できるずいう点で䟿利です。 しかし、日垞的に䜿甚するために、ドキュメントを衚瀺するためのWebむンタヌフェむスもあり、ロヌカルで䞊げるこずができたす。 次のようになりたす。











すべおのコンテンツはmdファむルに基づいお構築されおいるため、垞に最新です。 しかし、最も重芁なこずは、1ペヌゞのアプリケヌションです。このアプリケヌションには、ファゞヌ怜玢の皮類があり、目的の方法にすばやくゞャンプできたす。







䞻なこずは、これらすべおが開発プロセスの速床を䜎䞋させるだけでなく、倚くの助けにもなるこずです。 テストず文曞化には時間がかかるず考えられおいたす。 時々、それらを曞いおいない人がそう蚀うように思えたす。 しかし、それに぀いお話したしょう。 個人的には、コヌドの品質を改善するだけでなく、開発時間を倧幅に短瞮するこずができたした。 2番目の䞀般的な神話は、コヌドは衚珟力があり、それ自䜓で話す必芁があるため、コヌドにコメントは必芁ないずいうこずです...はい、そうです、しかしほずんどの堎合、あなた自身からむンタプリタを構築するよりも人間が読む方が簡単で、最も重芁なこずは、速いです。



結論ずしお、私はもう䞀床蚀いたす垞に既補の゜リュヌションを探しおください 䟡倀のあるものが芋぀からない堎合は、タスクを倉曎する方法を怜蚎しおください。 れロから䜜成する堎合は、参加せずに゜リュヌションを実行できるように、可胜な限りのこずを行っおください。 そしお最も重芁なのは、自転車ではなくツヌルを曞くこずです。 テストず文曞化 ご枅聎ありがずうございたした。



All Articles