web-dev-qa-db-ja.com

機能している成熟したコードをフレームワーク+パターンに置き換える価値があるのはいつですか

イントロ/質問

多くの場合、フレームワークが流行やトレンドになり、悪用されているのではないかと心配しています。多くの点で、人々は出てくるすべてのlibに追いつきたいという理由だけで、速度を犠牲にしています。私は、絶対に理にかなっている場合にのみ新しいライブラリとフレームワークを使用する、より保守的なアプローチを求めています。

関連: フレームワークを使用しない場合

更新/免責事項(2017年5月18日)

私は、迅速なアプリケーション開発、使いやすさ、および保守性が目標であるという結論に達しました。したがって、フレームワーク(新旧)は、最終製品にすばやく到達するのに役立つ場合は使用する必要があります。特別なケース(実際の測定可能なパフォーマンスの問題)が存在する場合にのみ、カスタムコードに切り替える必要があります...またはプロジェクト自体がレガシーであり、完全に書き換えるコストが高すぎる場合。

ケース

2008年から開発が続けられているTomcat6サーブレットの製品があり、その背後には何時間もの作業があります。コードは非常に成熟していますが、フレームワークを使用していません。

新しいチームメンバーは、すべてにフレームワークとパターンを使用するのが大好きです。フレームワークへの愛情を除けば、彼らはEdgeの新しいリリースの削減も大好きで、Tomcat6から新しいバージョン(JBOSS、GLASSFISH、Tomcat8)への移行を提案しています。

コアプロダクションサービスを、リリースされたばかりのコンテナー/サーバー/ Webサーバーに移動することは決してありません。

それをきれいに保つためにコードをリファクタリングすることに対してではありません!

私は、1秒あたり数千のリクエストを処理する本番コードに遅延を追加するフレームワークとパターンを追加することに反対しています。

下位互換性を維持しながらストリームへのシリアル化(JSON/XML)

リクエストが来ると、リクエストパラメータに関連するデータを含むXMLドキュメントとJSONドキュメントの両方を生成します。

古いクライアントの下位互換性を維持しているため、変更によって古いサポートが損なわれることはありません。 JSONとXMLの両方もサポートしているため、JacksonだけでなくKXMLライブラリも使用します。

どちらの形式でも、ストリーミングAPIを使用する2つの異なるシリアル化メソッドがあります。高速であることを除けば、下位互換性を維持するための柔軟性がはるかに高いこともわかりました。

メジャーバージョンとマイナーバージョンのシステムを使用するのが好きです。シリアル化メソッドのIFステートメントで追加した、シリアル化されたドキュメントに変更を加えるバックエンドへのすべてのマイナーな変更。かなりの数の変更が反映されたら(1年以上)、新しいシリアル化方法を追加します。したがって、version = 1.00から1.99を指定するすべてのリクエストは、serializeJSON1に送信されます。バージョン2から2.99を使用するすべてのリクエストは、serializeJSON2に送信されます。

オブジェクトに対してANNOTATIONSとMAPを使用するべきだという議論を聞いたことがあります。私が読んだストリーミングは最速なので、これは非常に嫌悪感を覚えます。

ストリーミングAPIを使用すると、必要な変更をその場で行うことができますが、MAPPINGでは、同じデータの複数のバージョンを異なるオブジェクトとして保存したり、他のフープを飛び越えたりする必要があります。

 output.startTag(null, TagTable.PRODUCT);

 output.startTag(null, TagTable.ID);
 output.text(ID);
 output.endTag(null, TagTable.ID);

 output.startTag(null, TagTable.DESCRIPTION);

 if (locale != null && Translations.containsKey(locale) && version >= 1)
     output.text(this.DescriptionURL + "/" + locale);
 else
     output.text(this.DescriptionURL);

 output.endTag(null, TagTable.LONGDESCRIPTION);

 if (version >= 1 && version < 1.5) {
     output.startTag(null, TagTable.POPULARITY);
     output.text(String.valueOf((int) this.pop));
     output.endTag(null, TagTable.POPULARITY);
 } else if (version >= 1.5) {
     output.startTag(null, TagTable.RATING);
     output.text(String.valueOf((int) this.rating));
     output.endTag(null, TagTable.RATING);
 }

上記の特定の3つのケースでは、動作中の成熟したコードを、追加のオーバーヘッドと追加の開発時間のコストがかかる可能性のあるフレームワーク/ライブラリ/パターンに置き換える意味が実際にはわかりません。

それで、動作する成熟したコードをフレームワーク+パターンに置き換える価値があるのはいつですか?

コメント?

更新:いくつかのベンチマーク

以前に投稿された最初の2つの例では、RESTとHASHMAPを使用しても、パフォーマンスにそれほど大きな違いはありませんが、コードが読みやすくなります。

ここで、ホットスポットで使用する場合のシリアル化に関するさらに興味深い問題について説明します。問題の実際のサーブレットには他のコードが多すぎるため、ストリーミングとマッピングをテストするためのおもちゃの例を作成しました。コードは次の場所にあります https://stackoverflow.com/questions/21781540/

必ずテストして、変更して、実行してください。

非常に興味深いのは、Javaのジャストインタイムオプティマイザーが時間の経過とともに違いを無視できるようになることです。したがって、マッピングとストリーミングのパーセンテージが、反復が増えるほど変化するのは次のとおりです。

Iter    Stream  Mapping
0       36,71%  63,29%
20      44,75%  55,25%
40      45,65%  54,35%
60      45,95%  54,05%
80      46,24%  53,76%
100     47,09%  52,91%
120     47,09%  52,91%
140     47,37%  52,63%
160     47,64%  52,36%
180     47,92%  52,08%
200     47,64%  52,36%
220     47,92%  52,08%
240     47,92%  52,08%
260     47,92%  52,08%
280     48,19%  51,81%
300     48,45%  51,55%
320     48,45%  51,55%
340     48,45%  51,55%
360     48,45%  51,55%
380     48,45%  51,55%
400     48,45%  51,55%
1000    48,72%  51,28%
2000    49,24%  50,76%
3000    49,24%  50,76%
4000    49,49%  50,51%
5000    49,75%  50,25%
6000    49,75%  50,25%
7000    49,75%  50,25%
8000    49,75%  50,25%
9000    49,75%  50,25%

また、もう一度再実行して、最初の20回の反復をより詳細にしました。

0   39,76%  60,24%
1   41,18%  58,82%
2   40,83%  59,17%
3   40,12%  59,88%
4   40,48%  59,52%
5   40,83%  59,17%
6   40,83%  59,17%
7   40,83%  59,17%
8   40,48%  59,52%
9   40,12%  59,88%
10  41,52%  58,48%
11  42,53%  57,47%
12  42,86%  57,14%
13  42,86%  57,14%
14  43,18%  56,82%
15  43,50%  56,50%
16  43,50%  56,50%
17  43,82%  56,18%
18  43,82%  56,18%
19  43,82%  56,18%
20  44,75%  55,25%

10,000回の反復後(またはJSON生成コードを1000回呼び出した後)は、VisualVMプロファイリング( visualVMスナップショットNPSファイル )のスクリーンショットです。

enter image description here

したがって、この最適化動作がTomcatサーブレットにも当てはまる場合、それは本当にマッピング(および他の多くの便利な関数/ JVNは時間の経過とともに最適化されるため、libs)。

結論

回答/コメントに基づいて、作業中の本番コードを書き直すかどうかは、ビジネス要件、および各プロジェクトの特定の費用便益分析の影響を受けると思います。

ベンチマークに基づくと、JIT JVMの最適化により、一部のlibs/frameworksを回避しても長期的には違いがないことが判明しました。

更新:コードを一晩中実行したままにした後

enter image description here

275,137回の反復と約30,000MSの後:

Mapping -   19,80%
Streaming -  80,20%

ここでJITの最適化がどのように行われるのか、そしてその動作がサーブレットに当てはまるのかどうか、本当に疑問に思います。

4
Menios

彼らが言うには

手の中の鳥は茂みの中の2羽よりも優れています

ここで適用されるのは、「しかし、XYまたはZのクールな新しいテクノロジーを使用するために、漠然と優れている」という幻想的な空想のためにすべてを分解するよりも、機能し、保守可能なものがある方が良いという意味です。クールな新技術を使用して」。

つまり、数年前に関数型言語で書き直したか、Ruby on Rails数年前、またはNode.js a 1年前、または...テクニカルブロゴスフィアで注目されるものは何もありません。これらは、「新しいものを使用する必要があります」という人々を満足させる安定した製品にはなりません。終了し、彼らは書き直したいと思うでしょう!

それで私は「あなたの問題は何ですか?」と尋ねなければなりません。あなたはあちこちで少し厄介かもしれない良いコードを持っていますが、私の広範な経験では、大きな書き直しを始めると、少し厄介なコードになってしまいます(ツールの経験がないためにすぐに実装されるか、時間のプレッシャーの下で行われることがよくあります戻ってきちんと修正することを約束します。)

フレームワークを使用するときは、新しいプロジェクトを実行していて、大量のコードを記述したいときです。フレームワークに移行して、自分で作成する必要のある退屈な定型文をすべて再利用するときです。フレームワークは使用されるため、特に既存のフレームワークがある場合は、フレームワークを選択することはありません(フレームワークは、それ自体で成長しているためフレームワークとは呼ばなくても、事実上1つです)。

注目すべき点の1つは、新しいテクノロジーの使用を主張する多くの人が、CVを向上させたい、または使用している既存のテクノロジーを学びたくないという2つの理由の1つを望んでいることを知っています。 (結局のところ、tech xを学ぶことは、実際に既存の製品に取り組むよりもずっと楽しいです)。私はすべての電話を疑いを持って扱います。どちらの場合でも、彼らの意図は製品またはビジネスの最善の利益ではないからです。

重いリファクタリング...それは別の話ですが、通常は良い話です。

7
gbjbaanb

うーん。いくつかのポイント:

  • 「私はそれが最速だと読んだ」。カルト主義者にならないでください。自分のためだと思います。自分で測定します。個人的には、手動でXMLを生成している場合、私はあなたの正気を疑います。
  • バグが潜んでいるものを知っている人あなたが知らないことを恐れるのは愚かで近視眼です。これは「ここで発明されていない」症候群につながり、より良いツールを学ぶ勇気を持ったプログラマーにすぐに渡されます。
  • フレームワークがパフォーマンスを妨げるランタイムパフォーマンスは非常に安いことがよくあります。プログラマーの時間はそうではありません。ここでのトレードオフは、これらのフレームワークが、コードの記述と保守にかかる時間を節約する代わりに、わずかなパフォーマンスの低下をもたらす可能性があることです。 XMLの例では、注釈とシリアライゼーションフレームワークを使用した場合、独自のXMLフォーマッターを作成してテストする必要はありません(読み取り:費用は会社にかかります)。

見てください-実行されテストされたコードは良いです。そして確かに、「それがあなたがすることになっていることだから」という理由でフレームワークを採用することは、悪いソフトウェアを作る良い方法です。しかし、これらの例は、単にあなたが変化を避けるための言い訳をしているように私を襲います。はい、変化は怖いです。はい、変更するとバグが発生する可能性があります。ただし、非効率性を排除し、コードを維持および拡張する能力を向上させるには、変更が必要です。

17
Telastyn