[Java] Alibaba Java 開発マニュアル


序文

提示:仅供学习参考使用

Alibaba Java 開発マニュアル、Java 開発では可能な限り開発ルールに従ってください。コーディングに非常に役立ちます~

この記事の内容はアリババ グループ技術部門による技術共有です。著作権はアリババ グループに属します。通信、学習、研究のみを目的としています。商用利用は禁止されています。違反者は起訴されます。


1. プログラミング規約

(1) ネーミングスタイル

  1. [必須] コード内の名前は、アンダースコアまたはドル記号で開始または終了することはできません。

    反例: _name / __name / $Object / name_ / name$ / Object$

  2. 【必須】 コード内でのネーミングにピンインと英語を混在させたり、中国語を直接使用したりすることは固く禁止されています。
    説明: 英語のスペルと文法が正しいと、読者は理解しやすくなり、曖昧さを避けることができます。たとえ純粋なピンインによる名前付けも
    避けるべきであることに注意してください。
    正例: alibaba / taobao / youku / hangzhou 等国际通用的名称, 可视同英文。
    反例: DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3

  3. [必須] クラス名は UpperCamelCase スタイルを使用し、次の例外を除いてキャメル ケースに従う必要があります: DO / BO /
    DTO / VO / AO
    正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
    反例: macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

  4. [必須] メソッド名、パラメーター名、メンバー変数、およびローカル変数はすべて lowerCamelCase スタイルを使用し、
    キャメル ケースに従う必要があります。
    正例: localValue / getHttpMessage() / inputUserId

  5. [必須] 定数名はすべて大文字にする必要があり、単語はアンダースコアで区切る必要があります。完全かつ明確な意味を表現するように努め、長い名前に不満を持たないでください。
    正例: MAX_STOCK_COUNT
    反例: MAX_COUNT

  6. [必須] 抽象クラス名は Abstract または Base で始まり、例外クラス名は Exception で終わり、テスト クラス
    名はテスト対象のクラス名で始まり Test で終わります。

  7. [必須] 角括弧は配列型の一部です。配列は次のように定義されます: String[] args;
    反例: String args[] を使用して定義します。

  8. [必須] POJO クラスのブール型変数に is を追加しないでください。追加しないと、一部のフレームワーク解析でシリアル化エラーが発生します。
    反例: 基本データ型 Boolean として定義された属性は isDeleted、そのメソッドも isDeleted() です。RPC フレームワークが逆解析を実行すると、対応する属性名が削除されたと「考えられ」、その結果、属性が取得されなくなります。そして例外をスローすること
    がよくあります。

  9. [必須] パッケージ名は小文字である必要があり、ドット区切り文字の間に自然な意味を持つ英単語が 1 つだけ存在する必要があります。パッケージ名は常に
    単数形を使用しますが、クラス名に複数の意味がある場合は、クラス名に複数形を使用できます。
    正の例: アプリケーション ツール クラスのパッケージ名は com.alibaba.open.util、クラス名は MessageUtils (このルールは
    Spring Framework 構造を参照します)

  10. 【必須】本文の意味を失わないよう完全に不規則な略語はやめてください。
    反例: AbstractClass "略語" の名前は AbsClass; 条件 "略語" の名前は condi このような任意の
    略語は、コードの可読性を著しく低下させます。

  11. [推奨] コードが一目瞭然という目的を達成するために、カスタム プログラミング要素に名前を付けるときは、
    その意味を表現するためにできるだけ完全な単語の組み合わせを使用してください。
    正例: 从远程仓库拉取代码的类命名为 PullCodeFromRemoteRepository。
    反例: 变量 int a; 的随意命名方式。

  12. [推奨] モジュール、インターフェイス、クラス、メソッドがデザイン パターンを使用している場合は、名前を付けるときに特定のパターンを反映します。
    注: 名前にデザイン パターンを反映すると、読者がアーキテクチャのデザイン コンセプトをすぐに理解できるようになります。
    正例: public class OrderFactory; public class LoginProxy; public class ResourceObserver;

  13. [推奨事項] インターフェイス クラスのメソッドとプロパティに修飾子を追加しないでください (public を追加しないでください)。コードは簡潔にして、
    有効な Javadoc コメントを追加してください。インターフェイスでは変数を定義しないようにしてください。変数を定義する必要がある場合、変数は
    インターフェイス メソッドに関連しており、アプリケーション全体の基本定数である必要があります。
    正例: 接口方法签名: void f(); 接口基础常量表示: String COMPANY = "alibaba";
    反例: 接口方法定义: public abstract void f();
    注: JDK8 のインターフェースではデフォルトの実装が許可されているため、このデフォルトのメソッドはすべての実装クラスにとって貴重なデフォルト
    実装です。

  14. インターフェイスと実装クラスの命名には 2 つのルール セットがあります。
    1) [必須] サービス クラスと DAO クラスの場合、SOA の概念に基づき、公開されるサービスはインターフェイスである必要があり、内部
    実装クラスはインターフェイスから区別されます。 Impl.の接尾辞。
    正例: CacheServiceImpl 实现 CacheService 接口。

2) [推奨] 機能を説明するインターフェイス名の場合は、対応する形容詞をインターフェイス名として使用します (通常は –able の形式)。
正例: AbstractTranslator 实现 Translatable。

  1. [参考] 列挙型クラス名には接尾辞 Enum を付けることを推奨し、列挙型メンバ名はすべて大文字で単語をアンダースコアで区切る必要があります。
    注: 列挙は実際には特別な定数クラスであり、コンストラクターはデフォルトで強制的にプライベートになります。
    正例: 枚举名字为 ProcessStatusEnum 的成员名称: SUCCESS / UNKOWN_REASON。

  2. 【参考】各層の命名規則:
    A) サービス/DAO層メソッドの命名規則
    1) 単一のオブジェクトを取得するメソッドには接頭辞getが付きます。
    2) 複数のオブジェクトを取得するメソッドには、リストという接頭辞が付けられます。
    3) 統計値の取得方法には先頭に count が付きます。
    4) 挿入メソッドには、save/insert という接頭辞が付きます。
    5) 削除メソッドには、remove/delete という接頭辞が付きます。
    6) 変更方法には先頭に update が付きます。
    B) ドメイン モデルの命名規則
    1) データ オブジェクト: xxxDO、xxx はデータ テーブルの名前です。
    2) データ転送オブジェクト: xxxDTO、xxx は業務分野に関連する名前です。
    3) 表示オブジェクト: xxxVO、xxx は通常 Web ページの名前です。
    4) POJO は DO/DTO/BO/VO の総称であり、xxxPOJO という名前を付けることは禁止されています。

(2) 定数の定義

  1. [必須] マジック値 (つまり、未定義の定数) をコード内に直接出現させることはできません。
    反例: String key = "Id#taobao_" + tradeId; cache.put(key, value);

  2. [必須] Long または Long を初期化するときは、小文字の l ではなく大文字の L を使用してください。小文字は数字の 1 と混同されやすく
    、誤解を招く可能性があります。
    説明: Long a = 2l; 数値として 21 と書きますか、Long として 2 と書きますか?

  3. 【推奨事項】 全ての定数を一つの定数クラスで管理するのではなく、機能に応じて分類し、個別に管理してください。
    注: 大規模で包括的な定数クラスの場合、変更された定数を見つけるには検索機能を使用する必要がありますが、これは理解と保守には役立ちません。
    正例: 缓存相关常量放在类 CacheConsts 下; 系统配置相关常量放在类 ConfigConsts 下。

  4. [推奨] 定数の再利用には、アプリケーション間で共有する定数、アプリケーション内で共有する定数、サブプロジェクト内で共有する定数、パッケージ内で共有する定数、クラス内で共有する定数の 5 つのレベルがあります

    1) アプリケーション間の共有定数: セカンドパーティのライブラリ (通常は client.jar の定数ディレクトリ) に配置されます。
    2) アプリケーション内の共有定数: ライブラリ (通常はモジュールの定数ディレクトリ) に配置されます。
    反例:理解しやすい変数は、アプリケーション内でも共有定数として統一して定義する必要があります。2 人のシージ エンジニアは、「
    はい」を表す変数を 2 つのクラスで定義しました:
    クラス A: public static Final String YES = "yes";
    クラス B: public static Final String YES = “y”;
    A.YES.equals(B.YES)、true であることが期待されていましたが、実際には false が返され、オンラインで問題が発生しました。
    3) サブプロジェクト内、つまり現在のサブプロジェクトの定数ディレクトリ内の共有定数。
    4) パッケージ内の共有定数: つまり、現在のパッケージの下の別の定数ディレクトリにあります。
    5) クラス内の共有定数: クラス内で直接プライベート静的な最終定義。

  5. [推奨] 変数値が範囲内でのみ変更され、名前を超える拡張属性がある場合は、列挙クラスとして定義します。以下の
    正の例の数字は拡張情報であり、曜日を示します。
    正例: public Enum { 月曜日(1)、火曜日(2)、水曜日(3)、木曜日(4)、金曜日(5)、土曜日(6)、日曜日(7);}

(3) コード形式

  1. [必須]中括弧の使用に関する条約。中括弧が空の場合は、改行なしで単に {} を記述します。
    空ではないコード ブロックの場合:
    1) 左中括弧の前に改行はありません。
    2) 左中括弧の後の改行。
    3) 右中括弧の前の改行。
    4) 右中括弧の後に else コードがある場合、改行は行われません。終了を示す右中括弧の後には改行が必要です。

  2. [必須] 左括弧と文字の間にはスペースがありません。同様に、右括弧と文字の間にはスペースがありません。詳細については、
    第 5 条の下にある正しいヒントの例を参照してください。
    反例:if (スペース a == b スペース)

  3. 【必須】if/for/while/switch/doなどの予約語と括弧の間にはスペースを入れる必要があります。

  4. [必須] 二項演算子または三項演算子の左側と右側にはスペースを追加する必要があります。
    注: 演算子には、代入演算子 =、論理演算子 &&、加算、減算、乗算および除算の記号などが含まれます。

  5. 【必須】インデントはスペース4文字とし、タブ文字の使用を禁止します。
    注: タブ インデントを使用する場合は、1 つのタブを 4 つのスペースに設定する必要があります。IDEA がタブを 4 つのスペースに設定する場合は、
    「タブ文字を使用」にチェックを入れないでください。Eclipse では、タブにスペースを挿入するにチェックを入れる必要があります。
    正例:(1 ~ 5 点を含む)

public static void main(String[] args) {
    
    
// 缩进 4 个空格
String say = "hello";
// 运算符的左右必须有一个空格
int flag = 0;
// 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号, 0 与右括号不需要空格
if (flag == 0) {
    
    
System.out.println(say);
}
// 左大括号前加空格且不换行;左大括号后换行
if (flag == 1) {
    
    
System.out.println("world");
// 右大括号前换行,右大括号后有 else,不用换行
} else {
    
    
System.out.println("ok");
// 在右大括号后直接结束,则必须换行
}
}
  1. [必須] コメントの二重スラッシュとコメントの内容の間には、スペースが 1 つだけ必要です。
    正例:// コメントの内容。// とコメントの内容の間にスペースがあることに注意してください。

  2. [必須] 1 行の文字数は 120 文字以内に制限されています。制限を超える場合は改行が必要です。改行する場合は、次の原則に従ってください。 1) 2 行目は 4 つのスペースでインデントされます
    。 3 行目からは、それ以上のインデントは必要ありません。例を参照してください。
    2) 演算子は以下のようにラップされます。
    3) メソッド呼び出しのドット記号は次のようにラップされます。
    4) メソッドを呼び出すときに、複数のパラメータをラップする必要がある場合は、カンマの後にラップします。
    5) 括弧の前で行を折り返さないでください。反例を参照してください。
    正例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,换行缩进 4 个空格, 点号和方法名称一起换行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");

反例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
("huang");
// 参数很多的方法调用可能超过 120 个字符, 不要在逗号前换行
method(args1, args2, args3, ...
, argsX);
  1. [必須] メソッドのパラメータを定義して渡すときは、複数のパラメータのカンマの後にスペースを追加する必要があります。
    正例:次の例では、実パラメータの「a」の後にスペースを入れる必要があります。
method("a", "b", "c");
  1. [必須] IDE のテキスト ファイル エンコーディングは UTF-8 に設定されており、IDE 内のファイルの改行文字は Windows 形式ではなく Unix 形式を使用します

  2. [推奨事項] 特定の行の文字を前の行の対応する文字と揃えるために、多数のスペースを追加する必要はありません。
    正例:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();

注: 変数 sb を追加する場合、位置合わせが必要な場合は、a、b、c にいくつかのスペースを追加する必要があります。変数が多い
場合、これは面倒です。

  1. [推奨]メソッド本体内の実行文グループ、変数定義文グループ、異なるビジネスロジックや異なるセマンティクスの間
    には空行を挿入してください。同じビジネス ロジックとセマンティクスの間に空行を挿入する必要はありません。
    注: 複数の空白行を挿入して区切る必要はありません。

(4) OOPプロトコル

  1. [必須] コンパイラの解析コストが不必要に増加するため、クラスのオブジェクト参照を介してこのクラスの静的変数または静的メソッドにアクセスすることは避けてください。クラス名を使用して直接アクセスしてください

  2. [必須] すべてのオーバーライド メソッドには @Override アノテーションを付ける必要があります。
    説明: getObject() および get0object() の問題。1 つは文字の O で、もう 1 つは数字の 0 です。 @Override を追加すると、
    オーバーライドが成功したかどうかを正確に判断できます。さらに、メソッド シグネチャが抽象クラスで変更された場合、その実装クラスはすぐにコンパイルして
    エラーを報告します。

  3. [必須] Java 変数パラメータは、同じパラメータ型および同じビジネス上の意味を持つ場合にのみ使用できます。オブジェクトの使用は避けてください。
    注: 変数パラメータはパラメータ リストの最後に配置する必要があります。(学生には、変数パラメータのプログラミングをできるだけ避けることが推奨されます)
    正例: public User getUsers(String type, Integer... ids) {...}

  4. [必須] 外部から呼び出されるインターフェイス、またはセカンドパーティ ライブラリが依存するインターフェイスは、インターフェイスの呼び出し側への影響を避けるためにメソッド シグネチャを変更することはできません
    インターフェイスが廃止された場合は @Deprecated アノテーションを追加する必要があり、新しいインターフェイスまたは新しいサービスを明確に記述する必要があります。

  5. 【必須】 古いクラスやメソッドは使用できません。
    注: java.net.URLDecoder のメソッド decode(String encodeStr) は廃止されたため、
    2 つのパラメータの decode(String source, String encode) を使用する必要があります。インターフェイス プロバイダーは明らかに廃止されたインターフェイスであるため、
    同時に新しいインターフェイスを提供する義務があり、呼び出し元として、廃止されたメソッドの新しい実装を検証する義務があります。

  6. 【必須】Objectのequalsメソッドはnullポインタ例外をスローしやすいため、equalsを呼び出すには定数または特定の値を持つオブジェクトを使用する必要があります

    正例:"test".equals(object);
    反例:object.equals("test");
    注: java.util.Objects#equals (JDK7 で導入されたツール クラス) を使用することをお勧めします。

  7. [必須] 同じ型のパッケージング クラス オブジェクト間の値の比較はすべて、equals メソッドを使用する必要があります。
    注: -128 ~ 127 の範囲の Integer var = ? 代入の場合、IntegerCache.cache に Integer オブジェクトが生成され、既存のオブジェクトが再利用されます。この範囲の整数値は == を使用して直接判断できますが、これは
    range それ以外のデータはすべてヒープ上に生成され、既存のオブジェクトは再利用されませんが、これは大きな落とし穴なので、
    equals メソッドを使用して判断することをお勧めします。

  8. 基本データ型とパッケージデータ型の使用基準は以下のとおりです。
    1) 【必須】すべてのPOJOクラス属性はパッケージデータ型を使用する必要があります。
    2) [必須] RPC メソッドの戻り値とパラメータはラップされたデータ型を使用する必要があります。
    3) [推奨] すべてのローカル変数に基本データ型を使用します。
    注: POJO クラス属性には、使用する必要があるときに値を明示的に割り当てる必要があることをユーザーに思い出させるための初期値がありません。NPE の問題やウェアハウス チェックはユーザーによって保証されます

    良い例: 基本的なデータ型での自動アンボックス化と受信には NPE リスクがあるため、データベースのクエリ結果が null になる可能性があります。
    反例: たとえば、合計トランザクション金額の増減、つまりプラスまたはマイナス x% を表示します。x は基本データ型で、呼び出しが失敗した場合に返される RPC サービスはデフォルト値です
    。ページには 0% が表示されますが、これは不合理です。ダッシュとして表示される必要があります。したがって、ラップされたデータ型の null 値は、
    リモート呼び出しの失敗や異常終了などの追加情報を表すことができます。

  9. 【必須】DO/DTO/VOなどのPOJOクラスを定義する場合は、属性のデフォルト値を設定しないでください。
    反例:POJO クラスの gmtCreate のデフォルト値は new Date() です。ただし、この属性には、データ抽出中に設定される特定の値がありません。このフィールドは、
    他のフィールドが更新されるときにも更新されるため、作成時刻が変更されます。現在の時刻。

  10. [必須] シリアル化クラスに新しい属性を追加するときは、逆シリアル化の失敗を避けるために、serialVersionUID フィールドを変更しないでください。逆シリアル化の混乱を避けるためにアップグレードと完全に
    互換性がない場合は、serialVersionUID 値を変更してください。
    注: 一貫性のないserialVersionUIDはシリアル化ランタイム例外をスローすることに注意してください。

  11. 【必須】コンストラクションメソッド内にビジネスロジックを追加することは禁止されており、初期化ロジックがある場合はinitメソッド内に記述してください。

  12. [必須] POJO クラスは toString メソッドを記述する必要があります。IDE ツールを使用する場合:source>generate toString
    、別の POJO クラスを継承する場合は、必ず先頭に super.toString を追加してください。
    注: メソッドの実行中に例外がスローされた場合、POJO の toString() メソッドを直接呼び出してその属性値を出力し、
    トラブルシューティングを容易にすることができます。

  13. 【推奨事項】 Stringのsplitメソッドで取得した配列にindexを使用してアクセスする場合、最後の区切り文字以降に内容があるか確認する必要があり、確認しないと
    IndexOutOfBoundsExceptionがスローされる危険性があります。
    例証します:

String str = "a,b,c,,";
String[] ary = str.split(",");
// 预期大于 3,结果是 3
System.out.println(ary.length

);

  1. [推奨事項] クラス内に複数のコンストラクタや同名のメソッドが存在する場合、
    読みやすくするためにこれらのメソッドをまとめて配置することをルール15より優先します。

  2. [推奨] クラス内のメソッドの定義順序は、パブリックメソッドまたはプロテクトメソッド>プライベートメソッド>ゲッター/セッター
    メソッドの順です。
    注: パブリック メソッドは、クラスの呼び出し元と管理者が最も関心のあるメソッドであり、最初の画面に表示されるのが最適です。保護されたメソッドはサブクラスのみに関係しますが、「テンプレート デザイン モード」ではコア メソッドになることもあります
    。 "; プライベート メソッドは通常は外部ではありませんが、ブラック ボックス実装であるため特別な注意が必要です
    。保持される情報の価値が低いため、Service および DAO のすべての getter/setter メソッドは
    クラス本体の最後に配置されます。

  3. [推奨事項] setter メソッドでは、パラメータ名はクラスのメンバ変数名と一致している必要があります (メンバー名 = パラメータ名)。getter/setter メソッドでは
    、トラブルシューティングの難易度を高めるためにビジネス ロジックを追加しないでください。
    反例:

public Integer getData() {
    
    
if (true) {
    
    
return this.data + 100;
} else {
    
    
return this.data - 100;
}
}
  1. [推奨] StringBuilder の append メソッドを使用して、ループ本体内で文字列接続メソッドを展開します。
    注: 逆コンパイルされたバイトコード ファイルは、各ループが新しい StringBuilder オブジェクトを作成し、その後
    追加操作を実行し、最後に toString メソッドを通じて String オブジェクトを返すため、メモリ リソースが浪費されることがわかります。
    反例:
String str = "start";
for (int i = 0; i < 100; i++) {
    
    
str = str + "hello";
}
  1. [推奨事項] Final ではクラス、メンバ変数、メソッド、ローカル変数を宣言できますが、以下の場合は Final キーワードを使用しません

    2) POJO クラスのドメイン変数など、参照されたドメイン オブジェクトの変更は許可されません。
    3) オーバーライドが許可されていないメソッド (POJO クラスのセッター メソッドなど)。
    4) 動作中に再割り当てされるローカル変数は許可されません。
    5) 変数のコンテキストの再利用を避け、最終的な記述を使用して変数の再定義を強制し、より適切な
    再構築を容易にします。

  2. [推奨] オブジェクトの clone メソッドを使用してオブジェクトをコピーする場合は注意してください。
    注: オブジェクトの clone メソッドはデフォルトで浅いコピーに設定されています。深いコピーを実装したい場合は、 clone メソッドをオーバーライドして属性 object をコピーする必要があります

  3. [推奨事項] クラスのメンバーとメソッドへの厳密なアクセス制御:
    1) new を使用して外部オブジェクトを直接作成できない場合は、コンストラクターをプライベートにする必要があります。
    2) ツール クラスには、パブリック コンストラクターまたはデフォルト コンストラクターを含めることはできません。
    3) クラスの非静的メンバー変数およびサブクラスと共有される変数は保護する必要があります。
    4) クラスの非静的メンバー変数はこのクラスでのみ使用され、プライベートである必要があります。
    5) クラスの静的メンバー変数がこのクラス内でのみ使用される場合、それらはプライベートである必要があります。
    6) 静的メンバー変数の場合は、それが最終的な変数であるかどうかを考慮する必要があります。
    7) クラス メンバー メソッドはクラス内の内部呼び出し専用であり、プライベートである必要があります。
    8) クラス メンバーのメソッドは継承されたクラスに対してのみパブリックであるため、保護されたものに制限されます。
    注: クラス、メソッド、パラメータ、または変数のアクセス範囲は厳密に制御されます。アクセス範囲が広すぎると、モジュールの分離には役立ちません。
    考え方: プライベート メソッドの場合は削除しても構いませんが、パブリック サービス メソッドや
    パブリック メンバー変数の場合は削除すると、手のひらに少し汗ばむでしょう? 変数は自分の子供のようなものなので、常に目の届く範囲に置くようにしてください
    。変数のスコープが大きすぎて制限なく走り回ると心配になります。

(5) 収集処理

  1. 【必須】hashCodeとequalsの処理については、以下のルールに従ってください。
    1)equalsを書き換える限り、hashCodeも書き換​​える必要があります。
    2) Set は一意のオブジェクトを格納し、hashCode と等しい値に基づいて判断されるため、
    Set に格納されたオブジェクトはこれら 2 つのメソッドをオーバーライドする必要があります。
    3) カスタム オブジェクトを Map のキーとして使用する場合は、hashCode と equals を書き換える必要があります。注: String は hashCode メソッドと equals メソッドをオーバーライドするため、String オブジェクトをキーとして
    問題なく使用できます。

  2. [必須] ArrayList の subList の結果を ArrayList にキャストすることはできません。そうでない場合は、ClassCastException がスローされます
    。つまり、 java.util.RandomAccessSubList を java.util.ArrayList にキャストすることはできません。
    注: subList は、ArrayList の内部クラス SubList を返します。 not ArrayList は ArrayList のビューです。SubList サブリストに対するすべての操作は、最終的には元のリストに反映されます。

  3. [必須] subList シナリオでは、元のコレクション内の要素の数の変更に細心の注意を払ってください。これにより、
    サブリストの走査、追加、または削除時に ConcurrentModificationException 例外が発生します。

  4. [必須] セットを配列に変換するメソッドを使用するには、セットの toArray(T[] array) を使用する必要があります。入力はまったく
    同じ型の配列で、サイズは list.size() です。 。注: toArray メソッドをパラメータとともに使用する場合、入力パラメータによって割り当てられた配列空間が十分に大きくない場合、配列要素が実際よりも大きい場合、
    toArray メソッドは内部でメモリ空間を再割り当てし、新しい配列アドレスを返します。
    必須の場合、添え字は [ list.size() ] です。配列
    要素は null に設定され、他の配列要素は元の値を保持するため、
    コレクション要素の数と一致するメソッド パラメーター グループ サイズを定義することが最善です。
    正例:

List<String> list = new ArrayList<String>(2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);

反例:toArray パラメータなしメソッドを直接使用する場合には問題があります。このメソッドの戻り値は Object[] クラスのみです。
他の型の配列を強制キャストすると、ClassCastException エラーが発生します。

  1. [必須] ツール クラス Arrays.asList() を使用して配列をコレクションに変換する場合、コレクションの変更に関連するメソッドは使用できません。
    その add/remove/clear メソッドは UnsupportedOperationException 例外をスローします。
    注: asList の戻りオブジェクトは Arrays 内部クラスであり、コレクション変更メソッドを実装しません。Arrays.asList は
    、インターフェイスのみを変換するアダプター モードを具体化しており、バックグラウンド データは依然として配列です。
    String[] str = new String[] { “you”, “wu” };
    リスト list = Arrays.asList(str);
    最初のケース: list.add(“yangguanbao”); 実行時例外。
    2 番目のケース: str[0] = “gujin”; の場合、list.get(0) もそれに応じて変更されます。

  2. [必須] 返されたデータを受け取るにはジェネリック ワイルドカード <? extends T> が使用されます。この方法で記述されたジェネリック コレクションには add メソッドは使用できません。また、<?
    super T> には get メソッドは使用できません。簡単です。割り当てをインターフェイスとして呼び出すときにエラーが発生します。
    注: PECS (Producer Extends Consumer Super) 原則を拡張してみましょう: まず、コンテンツを外部から頻繁に読み取る場合は
    、<? extends T> を使用するのが適切です。次に、頻繁に挿入する場合は、<?スーパーT>が適しています。

  3. [必須] foreach ループ内で要素の削除/追加操作を実行しないでください。要素の削除にはIterator
    メソッドを使用してください。同時に操作する場合はIteratorオブジェクトをロックする必要があります。
    正例:

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    
    
String item = iterator.next();
if (删除元素的条件) {
    
    
iterator.remove();
}
}

反例:

List<String> a = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
    
    
if ("1".equals(item)) {
    
    
list.remove(item);
}
}

注: 上記のコードの実行結果は、皆さんの予想を超えているはずですので、「1」を「2」に置き換えてみてください

  1. 【必須】JDK7以降のバージョンでは、Comparatorが以下の3つの条件を満たしている必要があります。満たさない場合、Arrays.sortおよび
    Collections.sortはIllegalArgumentException例外を報告します。
    注: 3 つの条件は次のとおりです
    。 1) x と y の比較結果は、y と x の比較結果と逆です。
    2) x>y、y>z、そして x>z。
    3) x=y の場合、x と z の比較結果は y と z の比較結果と同じになります。
    反例:次の例では等しい状況は処理されず、実際の使用では例外が発生する可能性があります:
    new Comparator() { @Override public int Compare(Student o1, Student o2) { return o1.getId() > o2.getId() ? 1 : -1; } };




  2. 【推奨】コレクションを初期化する場合は、コレクションの初期値サイズを指定します。
    注: HashMap は、HashMap(intInitialCapacity)、
    正例:initialCapacity = (保存される要素の数/負荷係数) + 1 を使用して初期化されます。なお、負荷率(ローダー
    ファクター)の初期値は0.75となっておりますが、一時的に初期値が決まらない場合はデフォルト値の16に設定してください。
    反例: HashMap は 1024 個の要素を配置する必要があります。容量の初期サイズが設定されていないため、要素が増加し続けると、容量は
    7 倍に拡張されます。サイズ変更にはハッシュ テーブルを再構築する必要があり、パフォーマンスに重大な影響を与えます。 。

  3. [推奨] keySet の代わりに、entrySet を使用して Map クラス コレクション KV を走査します。
    注: keySet は実際には 2 回走査されます。1 回目は Iterator オブジェクトに変換し、もう 1 回目はhashMap から
    キーに対応する値を取得します。entrySet は 1 回だけトラバースし、キーと値の両方をエントリに入れるため、
    より効率的です。JDK8の場合は、Map.foreachメソッドを使用します。
    正例:value() はリスト コレクション オブジェクトである V 値セットを返し、keySet() は Set コレクション オブジェクトである K 値セットを返し、
    entrySet() は KV 値組み合わせセットを返します。


  4. [参考] セットの順序 (ソート) と安定性 (オーダー) を適切に利用して、セットの無秩序 (アンソート) と不安定性 (アンオーダー) による悪影響を回避します。
    注: 順序性とは、走査結果が特定の比較ルールに従って順番に配置されていることを意味します。
    安定性とは、コレクション内の要素の順序が、走査されるたびに確実であることを意味します。例: ArrayList は順序付け/並べ替えなし、HashMap は並べ替えなし/並べ替えなし、TreeSet は
    並べ替え/並べ替えです。

  5. [参考] Set 要素の固有の特性を使用すると、
    走査、比較、および重複排除操作に List の contains メソッドを使用することなく、コレクションに対して重複排除操作を迅速に実行できます。

(6) 並行処理

  1. [必須] シングルトン オブジェクトを取得する場合はスレッドの安全性を確保する必要があり、メソッドもスレッドの安全性を確保する必要があります。
    注: リソース駆動クラス、ツール クラス、およびシングルトン ファクトリ クラスはすべて注意が必要です。

  2. [必須] エラー発生時のバックトラッキングを容易にするために、スレッドまたはスレッド プールを作成するときに意味のあるスレッド名を指定してください。
    正例:

public class TimerTaskThread extends Thread {
    
    
public TimerTaskThread() {
    
    
super.setName("TimerTaskThread");
...
}
  1. [必須] スレッド リソースはスレッド プールを通じて提供される必要があり、アプリケーションでのスレッドの明示的な作成は許可されません。
    注: スレッド プールを使用する利点は、スレッドの作成と破棄にかかる時間とシステム リソースのオーバーヘッドが削減され、
    リソース不足の問題が解決されることです。スレッド プールを使用しない場合、システムが同様のスレッドを多数作成し、メモリ消費や
    「過剰なスイッチング」問題が発生する可能性があります。

  2. [必須] スレッド プールは Executor を使用して作成することはできませんが、ThreadPoolExecutor を介して作成する必要があります。この
    処理方法により、書き込みを行う学生はスレッド プールの運用ルールをより明確に知り、リソース枯渇のリスクを回避できます。
    注: エグゼキュータによって返されるスレッド プール オブジェクトの欠点は次のとおりです。
    1)fixedThreadPool および SingleThreadPool:
    許可されるリクエスト キューの長さは Integer.MAX_VALUE であり、大量のリクエストが蓄積され、OOM が発生する可能性があります。
    2) CachedThreadPool および ScheduledThreadPool:
    作成できるスレッドの数は Integer.MAX_VALUE です。これにより、大量のスレッドが作成され、OOM が発生する可能性があります。

  3. [必須] SimpleDateFormat はスレッド非安全なクラスです。一般に、静的変数として定義すべきではありません。
    静的として定義されている場合は、ロックするか、DateUtils ツール クラスを使用する必要があります。
    良い例: スレッドの安全性に注意し、DateUtils を使用します。以下の治療法もお勧めします。

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
    
    
@Override
protected DateFormat initialValue() {
    
    
return new SimpleDateFormat("yyyy-MM-dd");
}
};

注: JDK8 アプリケーションの場合は、Date の代わりに Instant、Calendar の代わりに LocalDateTime、
SimpleDateFormat の代わりに DateTimeFormatter を使用できます。公式の説明では、「シンプルで美しく、強力で不変で、スレッド
セーフ」です。

  1. [必須] 同時実行性が高い場合、同期呼び出しではロックによるパフォーマンスの損失を考慮する必要があります。ロックフリーのデータ構造を使用できる場合は、ロックを使用しないでください。
    ブロックをロックできる場合は、メソッド本体全体をロックしないでください。オブジェクト ロックを使用できる場合は、クラス ロックを使用しないでください。
    注: ロックされたコード ブロックのワークロードをできるだけ小さくし、ロックされたコード ブロック内で RPC メソッドを呼び出さないようにしてください。

  2. [必須] 複数のリソース、データベース テーブル、オブジェクトを同時にロックする場合は、一貫したロック シーケンスを維持する必要があります。そうしないと、
    デッドロックが発生する可能性があります。
    注意: スレッド 1 は、更新操作を実行する前に、すべてのテーブル A、B、および C を順番にロックする必要があります。その後、スレッド 2 もテーブル A、B、および C を順番にロックする必要があります。そうしないと、
    デッドロックが発生する可能性があります。

  3. [必須] 同じレコードを同時に変更する場合、更新の損失を避けるためにロックが必要です。アプリケーション層でロックするか、キャッシュでロックする
    か、データベース層でオプティミスティックロックを使用し、更新基準としてバージョンを使用します。
    注: 各アクセス競合の確率が 20% 未満の場合は、楽観的ロックを使用することをお勧めします。それ以外の場合は、悲観的ロックを使用します。楽観的ロックの再試行回数は
    3 回以上である必要があります。

  4. 【必須】スケジュールされたタスクをマルチスレッドで並列処理する場合、Timer が複数の TimeTask を実行すると、いずれかのタスクがスローされた例外をキャッチしない限り、他のタスクは自動的に終了しますが、ScheduledExecutorService を使用するとこの問題は発生しません

  5. [推奨] 非同期から同期操作を実行するには、CountDownLatch を使用します。各スレッドは
    終了する前に countDown メソッドを呼び出す必要があります。スレッド実行コード内の catch 例外に注意して、メイン スレッドが実行できなくなることを避けるために countDown メソッドが確実に実行されるようにしてください
    await メソッドを使用すると、結果はタイムアウトになるまで返されません。
    注: 子スレッドによってスローされた例外スタックには、メインスレッドの try-catch では到達できないことに注意してください。


  6. [推奨] ランダムなインスタンスを複数のスレッドで使用することは避けてください。インスタンスの共有はスレッドセーフですが、同じシードの競合によるパフォーマンスの低下を引き起こします。
    注: ランダム インスタンスには、java.util.Random または Math.random() メソッドのインスタンスが含まれます。
    正例:JDK7 以降では、API ThreadLocalRandom を直接使用できますが、JDK7 より前は、
    各スレッドがインスタンスを保持するようにコーディングする必要があります。


  7. [推奨事項] 同時実行シナリオでは、二重チェック ロック (「二重チェック ロックが壊れている」宣言を参照) による遅延初期化の実装に隠れた最適化の問題があり、これはより単純な推奨
    ソリューション) )、ターゲット属性を volatile として宣言します。
    反例:

class Singleton {
    
    
private Helper helper = null;
public Helper getHelper() {
    
    
if (helper == null) synchronized(this) {
    
    
if (helper == null)
helper = new Helper();
}
return helper;
}
// other methods and fields...
}
  1. [参考] volatile はマルチスレッドにおける不可視メモリの問題を解決します。1 回の書き込みと多数の読み取りの場合、変数の同期の問題は解決できます
    が、書き込みが多数の場合、スレッドの安全性の問題は解決できません。count++ 操作の場合は、次のクラスを使用して実装します:
    AtomicInteger count = new AtomicInteger(); count.addAndGet(1); JDK8 の場合は、
    AtomicLong よりもパフォーマンスの良い LongAdder オブジェクトを使用することをお勧めします。 (楽観的ロックの再試行回数が減ります)。

  2. 【参考】HashMapのリサイズ容量が不足している場合、同時実行性が高くデッドリンクが発生し、CPU負荷が高くなる可能性がありますが、開発時には他の
    データ構造やロックを利用することでこのリスクを回避できます。

  3. [参考] ThreadLocal では共有オブジェクトの更新問題を解決できないため、 ThreadLocal オブジェクトの静的
    変更を使用することをお勧めします。この変数はスレッド内のすべての操作で共有されるため、静的変数として設定されます。このようなすべてのインスタンスは
    この静的変数を共有します。つまり、クラスが初めて使用されるとき、クラスはロードされ、ストレージの一部のみになります。スペースが割り当てられます。オブジェクトは (
    このスレッド内で定義されている限り) この変数を操作できます

(7) 制御文


  1. [必須] switch ブロック内では、各ケースをブレー​​ク/リターンなどで終了するか、プログラムがどのケースで実行を継続するかを示すコメントで終了する必要があります; switch ブロック内では、default ステートメントを含めて
    配置する必要があります。コードはありません。
  2. [必須] if/else/for/while/do ステートメントでは中括弧を使用する必要があります。コードが 1 行しかない場合でも、
    次のような単一行のコーディングは避けてください。
  3. [推奨] 異常な分岐を表現する場合は、if-else メソッドをあまり使用しないでください。このメソッドは次のように書き換えることができます。
if (condition) {
    
    
...
return obj;
}
// 接着写 else 的业务逻辑代码;

注: ロジックを表現するために if()…else if()…else… を使用する必要がある場合、[必須]
その後のコードのメンテナンスが困難になるのを避けるため、3 レベルを超えないようにしてください。
良い例: ガード ステートメント、ストラテジ パターン、ステート パターンなどを使用して、3 レベルを超える if-else 論理判定コードを実装できます。
ガード ステートメントの例は次のとおりです。

public void today() {
    
    
if (isBusy()) {
    
    
System.out.println(“change time.);
return;
}
if (isFree()) {
    
    
System.out.println(“go to travel.);
return;
}
System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.);
return;
}
  1. [推奨] 一般的なメソッド(getXxx/isXxxなど)を除き、条件判定では他の複雑な文を実行せず、可読性を
    高めるために複雑な論理判定の結果を意味のあるブール変数名に代入してください。
    注: 多くの if ステートメントのロジックは非常に複雑です。読者は、どの条件がどのステートメントを実行するかを知るために、条件式の最終結果を分析する必要があります。それでは、読者が
    論理式を誤って分析した場合はどうなるでしょうか?
    正例:

```dart
// 伪代码如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
    
    
...
}

反例:

if ((file.open(fileName, "w") != null) && (...) || (...)) {
    
    
...
}

  1. [推奨事項] ループ本体内のステートメントはパフォーマンスを考慮し、オブジェクト、変数の定義、データベース接続の取得、不要な try-catch 操作などの次の操作をできるだけループの外に移動する必要があります (この操作は可能ですか? catch をループの外に移動できますか?)。

  2. [推奨] インターフェイス入力パラメーターの保護 このシナリオは、バッチ操作に使用されるインターフェイスに一般的です。

  3. 【参考】パラメータの検証は以下の場合に必要となります。
    1) 呼び出される頻度が少ないメソッド。
    2) 実行時間のオーバーヘッドが大きいメソッド。この場合、パラメーターの検証時間はほとんど無視できますが、
    中間の実行がロールバックしたり、パラメーター エラーによりエラーが発生したりすると、ゲインがゲインを上回ります。
    3) 極めて高い安定性と可用性を必要とする方式。
    4) RPC/API/HTTP インターフェースなど、外部に提供されるオープンインターフェース。
    5) 機密性の高いアクセス許可の入り口。

  4. 【参考】 以下の場合にはパラメータの検証は必要ありません。
    1) ループ内で呼び出される可能性が高いメソッド。ただし、外部パラメータのチェック要件はメソッドの説明に記載する必要があります。
    2) 基になるメソッドがより頻繁に呼び出されます。結局のところ、これは純水濾過の最終ステップのようなもので、パラメータのエラーによって
    最下層まで問題が露呈する可能性は低いです。通常、DAO レイヤーとサービス レイヤーは同じアプリケーション内にあり、同じサーバーにデプロイされるため、
    DAO パラメーターの検証は省略できます。
    3) private として宣言されたメソッドは、独自のコードによってのみ呼び出されます。メソッドを呼び出すコードによって渡されるパラメータが
    チェックされているか、まったく問題がないことが確認できる場合は、メソッドでパラメータを検証する必要はありません。この時。

(8) 注釈規定

  1. [必須] クラス、クラス属性、およびクラス メソッドに関するコメントは Javadoc 仕様を使用する必要があり、 /* content
    /format を使用し、 // xxx メソッドは使用できません。
    注: IDE 編集ウィンドウでは、Javadoc モードにより関連するコメントが表示され、生成された Javadoc は対応するコメントを正しく出力できます。IDE では、
    プロジェクトがメソッドを呼び出すときに、メソッド、パラメータ、および戻り値の意味を確認できます。メソッドに入らずに一時停止できるため、
    読み取り効率が向上します。

  2. [必須] すべての抽象メソッド (インターフェイス内のメソッドを含む) は、Javadoc でコメントする必要があります。戻り値、パラメータ、例外の説明に加えて、
    メソッドが何を行うか、どのような機能を実装するかも示す必要があります。
    注: サブクラスの実装要件や呼び出しの注意事項について説明してください。

  3. [必須] すべてのクラスに作成者と作成日を追加する必要があります。

  4. [必須] メソッド内の単一行コメント。コメントされたステートメントの上に新しい行を開始し、// comment を使用します。メソッド内の複数行のコメント
    には /* */ コメントを使用し、コードと必ず揃えてください。

  5. [必須] すべての列挙型フィールドには、各データ項目の目的を説明するコメントが必要です。

  6. [推奨] 中途半端な英語でコメントするよりも、中国語のコメントを使って問題をわかりやすく説明した方がよいでしょう。固有名詞やキーワードは
    英語の原文のままで構いません。
    反例: 「TCP 接続タイムアウト」は「伝送制御プロトコル接続タイムアウト」として解釈されますが、これは理解するのがさらに面倒です。

  7. [推奨事項] コードを変更する場合、特に
    パラメータ、戻り値、例外、コア ロジックなどの変更については、それに応じてコメントも変更する必要があります。
    注: 道路網やナビゲーション ソフトウェアの更新が同期していないのと同じように、コードと注釈の更新も同期していません。ナビゲーション ソフトウェアの遅れが深刻な場合、
    ナビゲーションの意味が失われます。

  8. 【参考】 コードは丁寧にコメントアウトしてください。単にコメントアウトするのではなく、上記を詳しく説明します。無駄であれば削除してください。
    注: コードがコメントアウトされる可能性は 2 つあります。 1) このコードのロジックは後で復元されます。2) 絶対に使用しないでください。
    前者に発言情報がないと、アノテーションの動機を知ることが困難となる。後者は直接削除することをお勧めします (コード ウェアハウスには履歴コードが保存されます)。


  9. [参考] コメントの要件: 第一に、設計アイデアとコード ロジックを正確に反映できること、第二に、他のプログラマーがコードの背後にある情報をすぐに理解できるように、ビジネス上の意味を説明できることです。コメントがまったくない大部分のコードは、読者にとっては聖典のようなものです
    コメントは自分が読むためのもので、時間が経っても当時の考え方がよくわかりますし、後任者のためのコメントでもあります
    彼らがあなたの仕事をすぐに引き継ぐことができるように、読んでください。

  10. [参考] 適切な名前付けとコード構造は一目瞭然であり、コメントは簡潔、正確、表現力豊かである必要があります。
    コメントの極端な多すぎ、過剰なコメントは避けてください。コードのロジックを変更すると、コメントの変更はかなりの負担になります。
    反例:
    // エレファントを冷蔵庫に入れる
    put(elephant, fridge);
    メソッド名 put と 2 つの意味のある変数名 elephant と Bridge で、これが何をしているのかがすでに説明されており、
    セマンティクスが明確なコードには追加のコメントは必要ありません。

  11. 【参考】特別なコメントマークについては、マークした人、マークした時刻を明記してください。これらのマークをタイムリーに処理するよう注意し、
    マーク スキャンを通じてこのようなマークを頻繁に清掃してください。オンライン障害は、これらのマークのコードに起因する場合があります。
    1) To Do 項目 (TODO): (マークする人、マークする時間、[推定処理時間]) は、
    実装する必要があるがまだ実装されていない機能を示します。これは実際には Javadoc タグであり、現在の Javadoc は
    まだ実装されていませんが、広く使用されています。クラス、インターフェース、およびメソッドにのみ適用できます (Javadoc タグであるため)。
    2) エラー、動作できません (FIXME): (マーク名、マーク時間、[推定処理時間])
    コメント内で FIXME を使用して、特定のコードが間違っていて動作せず、時間内に修正する必要があることをマークします。

(9) その他

  1. 【必須】正規表現を使用する場合は、プリコンパイル機能をうまく利用して、正規表現のマッチングを効果的に高速化します。
    注: メソッド本体では定義しないでください。 Pattern pattern = Pattern.compile(rule);


  2. 【必須】VelocityがPOJOクラスの属性を呼び出す場合、属性名を直接使用して値を取得することを推奨します仕様に従い、テンプレートエンジンが自動的にPOJOのgetXxx()を呼び出します。データ型変数 (ブール名の前に is を付ける必要はありません
    ) を指定すると、 isXxx() メソッドが自動的に呼び出されます。
    注: ブール型ラッパー クラス オブジェクトの場合は、getXxx() メソッドが最初に呼び出されることに注意してください。

  3. [必須] バックグラウンドでページに送信される変数を追加する必要があります! var - 真ん中に感嘆符。注: var = null または存在しない場合、!{var} - 真ん中の感嘆符。説明: var=null または存在しない場合、! v a r -真ん中の感嘆符。説明: v a rの場合=nullまたは存在しない場合、 {var} がページに直接表示されます

  4. [必須] Math.random() は double 型を返すことに注意してください。値の範囲は 0≤x<1 であることに注意してください (
    ゼロ値も取得できますが、ゼロ除算の例外に注意してください)。整数型の乱数。使用しないでください。 x は、
    Random オブジェクトの nextInt または nextLong メソッドを直接使用して、10 の数倍に拡大されてから四捨五入されます。

  5. [必須] new Date().getTime(); の代わりに System.currentTimeMillis(); を使用して現在のミリ秒数を取得します
    注: より正確なナノ秒の時間値を取得したい場合は、System.nanoTime() を使用します。JDK8 では、
    統計時間などのシナリオには Instant クラスを使用することをお勧めします。

  6. [推奨] ビュー テンプレートに複雑なロジックを追加しないでください。
    注: MVC 理論によれば、ビューはプレゼンテーションを担当し、モデルとコントローラーの作業を引き受けるべきではありません。

  7. [推奨事項] データ構造が無制限に増大してメモリを使い果たさないように、データ構造の構築時または初期化時にそのサイズを指定する必要があります。

  8. [推奨] 使用されなくなったコード セグメントまたは構成情報を適時にクリーンアップします。
    注: 過度に肥大化したプログラムや冗長なコードを避けるために、ジャンク コードや古い構成を断固としてクリーンアップします。良い例: 一時的にコメント アウトされ、後で再利用される可能性があるコード スニペットの場合、コードをコメント アウトする理由を説明するために、コメントされたコードの上に
    3 つのスラッシュ (///) を使用することが統一的に規定されています。

2. 例外ログ

(1) 例外処理

  1. [必須] Java クラス ライブラリで定義されているタイプの RuntimeException は、事前チェックによって回避できますが、
    IndexOutOfBoundsException、NullPointerException などの catch によって処理されるべきではありません。
    注: 外部から送信された文字列数値を解析する場合など、事前チェックを通過できない例外を除き、
    NumberFormatException をキャッチすることで実装されます。
    正例:if (obj != null) {…}
    反例:try { obj.method() } catch (NullPointerException e) {…}

  2. 【必須】例外は条件分岐に比べて処理効率が低いため、処理制御や条件制御では使用しないでください。

  3. [必須] コードの大部分を試してみてください。これは無責任です。
    キャッチする際には、安定したコードと不安定なコードを区別してください。安定したコードとは、何をしても問題が発生しないコードを指します。不安定なコードをキャッチする場合は、
    例外の種類をできる限り区別して、対応する例外を処理するようにしてください。

  4. [必須] 例外を処理するには、例外をキャッチします。例外をキャッチせず、何も処理せずに破棄します。処理したくない場合は、呼び出し元に
    例外をスローしてください。最も外側のビジネス ユーザーは例外を処理し、例外を
    ユーザーが理解できるコンテンツに変換する必要があります。

  5. 【必須】トランザクションコードにtryブロックを入れる 例外をキャッチした後にトランザクションをロールバックする必要がある場合は、手動でトランザクションをロールバックするように注意する必要があります

  6. [必須]finally ブロックはリソース オブジェクトとストリーム オブジェクトを閉じ、例外が発生した場合は try-catch する必要があります。
    注: JDK7 以降の場合は、try-with-resources メソッドを使用できます。

  7. 【必須】finallyブロック内でreturnは使用できません、finallyブロック内でreturnが返った後、メソッドの実行は終了し、
    tryブロック内のreturn文は実行されません。

  8. [必須] キャッチされた例外とスローされた例外は正確に一致する必要があります。そうでない場合、キャッチされた例外はスローされた例外の親クラスです。
    注: 相手がアジサイボールを投げるつもりで実際に砲丸投げを受けた場合、予期せぬ事態が発生します。

  9. [推奨事項] メソッドの戻り値は null であっても構いません。空のコレクションや空のオブジェクトを強制的に返す必要はありません。どのような状況で null 値が返されるかを完全に説明するコメントを追加する必要があります
    NPE の問題を防ぐために、呼び出し元は null 判定を実行する必要があります。
    注: このマニュアルでは、NPE の防止は呼び出し側の責任であることを明確にしています。呼び出されたメソッドが空のコレクションや空のオブジェクトを返したとしても、呼び出し元にとっては安心できる状況ではなく、
    リモート呼び出しの失敗、シリアル化の失敗、実行時例外などのシナリオで
    null を返す状況を考慮する必要があります。

  10. [推奨事項] NPE を防ぐことはプログラマーの基本スキルです。NPE が発生するシナリオに注意してください:
    1) 戻り値の型が基本データ型である。戻り値がデータ型のオブジェクトをラップする場合、自動アンボックス化により NPE が発生する可能性があります。
    反例: public int f() { return Integer object}。null の場合、自動的にアンボックス化され、NPE がスローされます。
    2) データベースのクエリ結果が null になる可能性があります。
    3) コレクション内の要素が isNotEmpty であっても、取り出されたデータ要素が null の場合があります。
    4) リモート呼び出しがオブジェクトを返す場合、NPE を防ぐために常に null ポインタの判定が必要です。
    5) セッションで取得したデータについては、NPE をチェックして null ポインタを回避することをお勧めします。
    6) obj.getA().getB().getC() へのカスケード呼び出し; 一連の呼び出しにより、NPE が簡単に発生する可能性があります。
    正例:NPE の問題を防ぐには、JDK8 の Optional クラスを使用します。

  11. 【推奨事項】 定義時に非チェック例外/チェック例外を区別し、new RuntimeException()を直接スローすることは避け、
    ExceptionやThrowableのスローを許可せず、業務上の意味を持つカスタム例外を使用すること。
    DAOException / ServiceException など、業界で定義されているカスタム例外を推奨します。

  12. 【参考】コード内で「例外スロー」を使用するか「エラーコードを返す」を使用するか、社外のhttp/apiオープンインターフェースでは「エラーコード」を使用する必要がある、アプリケーション内では例外スローを推奨、クロスを
    優先する-application RPC は結果モードを呼び出し、
    isSuccess() メソッド、「エラー コード」、および「エラー概要情報」をカプセル化します。
    注: RPC メソッドの戻りに Result メソッドを使用する理由:
    1) 例外戻りメソッドを使用すると、呼び出し側が例外をキャッチしないと実行時エラーが発生します。
    2) スタック情報を追加せず、新しいカスタム例外を作成して独自のエラー メッセージを追加するだけの場合、
    呼び出し側の問題解決にはあまり役に立ちません。スタック情報を追加した場合、
    呼び出しエラーが多発した場合、データのシリアル化や送信のパフォーマンス低下も問題となります。

  13. 【参考】コードの重複を避ける(Don't Reply Yourself)、すなわちDRY原則。
    注: コードを自由にコピーして貼り付けると、必然的にコードの重複が発生し、将来変更が必要になった場合は、すべてのコピーを変更する必要があるため、見落としがちです
    必要に応じて、共通メソッド、抽象パブリック クラスを抽出するか、それらをコンポーネント化することもできます。
    良い例: クラス内に複数のパブリック メソッドがあり、それらはすべて同じパラメーター検証操作を複数行実行する必要があります。このとき、以下を抽出してください: private boolean checkParam(DTO
    dto) {…}

(2) ログプロトコル

  1. 【必須】アプリケーションはログシステム(Log4j、Logback)のAPIを直接利用することはできませんが、
    ログフレームワークSLF4JのAPIを利用する必要があります。ファサードモードのログフレームワークを利用することで、それぞれのログ処理方法の保守・統一に役立ちます。クラス。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
  1. [必須] 一部の例外は毎週発生する特性があるため、ログ ファイルは少なくとも 15 日間保存することをお勧めします。

  2. [必須] アプリケーションの拡張ログ(管理、一時監視、アクセスログなど)の命名方法:
    appName_logType_logName.log。logType: ログ タイプ、推奨カテゴリには
    stats/desc/monitor/visit などが含まれます; logName: ログの説明。この種の名前付けの利点は、
    ファイル名によってログ ファイルがどのアプリケーション、タイプ、目的に属しているかを知ることができるため、分類や検索にも役立ちます。
    正例:タイム ゾーン変換の例外は、mppserver アプリケーションで次のように個別に監視されます。
    mppserver_monitor_timeZoneConvert.log
    説明: エラー ログとビジネス ログを別々に保存するなど、ログを分類することをお勧めします。これは、開発者が表示するのに便利です。
    ログを通じてシステムをタイムリーに監視するのに便利です。

  3. [必須] トレース/デバッグ/情報レベルのログ出力の場合、条件付き出力を使用するか、プレースホルダーを使用する必要があります

    説明: logger.debug("ID: " + id + " およびシンボル: " + シンボルの取引を処理しています);
    ログ レベルが警告の場合、上記のログは出力されませんが、文字列の結合操作が実行されます。シンボルがオブジェクトである場合、
    toString() メソッドが実行され、システム リソースが浪費されます。上記の操作を実行した後、最終的なログは出力されません。
    正例: (条件)

if (logger.isDebugEnabled()) {
    
    
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}

正例: (占位符)

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
  1. [必須] ログを繰り返し出力してディスク領域を無駄にしないように、log4j.xml で additivity=false を必ず設定してください。
    正例: <logger name="com.taobao.dubbo.config" additivity="false">

  2. 【必須】例外情報には、犯罪現場情報と例外スタック情報の 2 種類の情報を含める必要があります。処理されない場合は、
    throws キーワードを通じて上にスローされます。
    正例: logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);

  3. [推奨] ログを注意深く記録してください。運用環境でのデバッグ ログの出力は禁止されており、情報ログの選択的な出力が行われ、最初の起動時にビジネス動作情報を記録するために warn を使用する場合は、
    サーバー ディスクのバーストを避けるためにログ出力の量に注意する必要があります
    。タイムログ内のこれらの観察を忘れずに削除してください。
    注: 大量の無効なログを出力すると、システムのパフォーマンスが向上したり、エラー ポイントを迅速に特定したりすることはできません。ログを記録するときは、次
    のことを考えてください。本当にこれらのログを読んでいる人はいるのでしょうか? このログを見た後、何ができるでしょうか? トラブルシューティングにメリットをもたらすでしょうか?

  4. [参考] 警告ログレベルを使用して、ユーザー入力パラメータのエラーを記録し、ユーザーからの苦情に困惑することを避けることができます
    ログ出力レベルに注意してください。エラーレベルには、システムロジックエラーや例外などの重要なエラー情報のみが記録されます。必要がない限り
    、このシナリオではエラー レベルを入力しないでください。

3. 単体テスト

  1. [必須] 優れた単体テストは AIR 原則に準拠している必要があります。
    注: 単体テストをオンラインで実行すると、空気 (AIR) が存在しないように感じられますが、
    テストの品質を保証することは非常に重要です。マクロの観点から見ると、優れた単体テストには自動化、独立性、反復実行という特徴があります。
    A:自動
    I:独立
    R:繰り返し可能

  2. [必須] 単体テストは完全に自動化され、非対話型である必要があります。通常、テスト フレームワークは定期的に実行され、
    意味のある実行プロセスを完全に自動化する必要があります。出力に手動レビューが必要なテストは、良い単体テストとは言えません。System.out は単体テスト
    での人による検証に使用することは許可されていないため、検証には Assert を使用する必要があります。

  3. [必須] 単体テストの独立性を維持します。単体テストの安定性、信頼性、保守が容易であることを保証するために、単体テスト ケースは
    相互に呼び出したり、実行順序に依存したりしてはなりません。
    反例: method2 需要依赖 method1 的执行, 将执行结果做为 method2 的输入。

  4. [必須] 単体テストは繰り返し実行でき、外部環境の影響を受けません。
    注: 単体テストは通常​​、継続的インテグレーションに配置され、コードがチェックインされるたびに単体テストが実行されます。
    1 つのテストが外部環境 (ネットワーク、サービス、ミドルウェアなど) に依存している場合、継続的統合メカニズムが容易に利用できなくなる可能性があります。良い例: 外部環境の影響を受けないようにするために、コード設計時にSUTの依存関係をインジェクションに変更し、テスト時にSpringなどのDIフレームワークを使用し
    てローカル(メモリ)実装やMock実装をインジェクションする必要がある。

  5. [必須] 単体テストの場合、問題を正確に特定できるようにテストの粒度が十分小さいことを確認してください。単一の測定の粒度は最大でもクラス レベル
    、通常はメソッド レベルです。
    注: テストの粒度が小さい場合にのみ、エラーが発生したときにエラーの場所をできるだけ早く特定できます。単一テストは、クラス間またはシステム間の
    対話ロジック、つまり統合テストの領域をチェックする責任を負いません。

  6. [必須] コア ビジネス、コア アプリケーション、およびコア モジュールの増分コードは、単体テストに合格することを保証します。
    注: 新しいコードは適時に単体テストに追加する必要があります。新しいコードが元の単体テストに影響を与える場合は、適時に修正してください。

  7. [必須] 単体テストコードはプロジェクトディレクトリ src/test/java に記述する必要があり、業務コードディレクトリには記述できません。
    注: このディレクトリはソース コードのビルド時にスキップされ、単体テスト フレームワークはデフォルトでこのディレクトリをスキャンします。

  8. [推奨事項] 単体テストの基本目標: ステートメント カバレッジが 70% に達すること、コア モジュールのステートメント カバレッジとブランチ カバレッジが
    100% に達する
    こと 注: エンジニアリング仕様のアプリケーション階層化、Services に記載されている DAO 層と Manager 層再利用性が高い場合は
    単体テストを行う必要があります。

  9. [推奨事項] テストされるモジュールの配信品質を保証するために、単体テスト コードを作成するときは BCDE 原則に従ってください。
    B: 境界、境界値のテスト。ループ境界、特殊な値、特殊な時点、データの順序などを含みます。
    C: 入力を正しく修正し、期待どおりの結果を取得します。
    D: 設計ドキュメントと組み合わせて単体テストを作成する設計。
    E:エラー。エラー情報(不正なデータ、異常な処理、業務外の入力など)の入力を強制され、期待した結果が得られます

  10. [推奨事項] データベース関連のクエリ、更新、削除などの操作では、データベース内のデータが存在することを前提としたり、データベースを直接操作してデータを
    挿入したりすることはできません。データを挿入またはインポートするプログラムを使用して、データを準備してください。データ。
    反例:データベース内の特定の行のデータを削除する単体テストでは、まず手動で削除対象の行を追加しますが、
    この行の新規データは業務挿入ルールに準拠しておらず、テスト結果が異常となります。

  11. [推奨] データベースに関連する単体テストの場合は、データベースにダーティなデータが発生することを避けるために、自動ロールバック メカニズムをセットアップできます。または、
    単体テストによって生成されたデータに明確なサフィックスとサフィックスを付けます。
    正例:RDC の内部単体テストでは、プレフィックス RDC_UNIT_TEST_ を使用してデータを識別します。

  12. [推奨事項] テスト不可能なコードについては、必要なリファクタリングを実行してコードをテスト可能にし、
    テスト要件を満たすために非標準のテスト コードの作成を避けることをお勧めします。


  13. [推奨] 設計レビューの段階で、開発者はテスターと協力して単体テストの範囲を決定する必要がありますが、単体テストではすべてのテスト ケース (UC) をカバーすることが最適です。


  14. [推奨事項] 単体テストは品質保証手法です。プロジェクトリリース後に単体テストケースを追加することは推奨されません。プロジェクトをテストに提出する前に単体テストを完了することをお勧めします。

  15. [参考] 単体テストをより便利にするために、ビジネス コードでは次のような状況を避ける必要があります。
    コンストラクター メソッドで多くのことを実行しすぎます。
    グローバル変数と静的メソッドが多すぎます。
    外部依存関係が多すぎます。
    条件文が多すぎます。
    注: ガード ステートメント、戦略パターン、状態パターンなどを使用して、多層条件ステートメントを再構築することをお勧めします。

  16. 【参考】単体テストについて次のような誤解をしないでください。
    それはテストのクラスメートが行うことです。この記事は開発マニュアルであり、この記事の内容は開発学生に非常に関連性があります。
    単体テストのコードが冗長です。車の全体的な機能は、各ユニット部品のテストが正常であるかどうかに大きく関係します。
    単体テスト コードはメンテナンスを必要としません。1 年半が経過すると、単体テストはほぼ放棄された状態になります。
    単体テストはオンラインの失敗と弁証法的な関係はありません。単体テストを適切に行うと、オンラインでの失敗を最大限に回避できます。

4. 安全規制

  1. [必須] ユーザーに属するページまたは機能は、権限制御の検証を受ける必要があります。説明: 他の人のプライベート メッセージの内容を表示したり、他の人の注文を変更したりする
    など、水平的な権限の検証を実行せずに、他の人のデータに自由にアクセス、変更、削除できないようにします。

  2. [必須] 機密性の高いユーザー データを直接表示することは禁止されており、表示データは機密性を解除する必要があります。
    注: 個人の携帯電話番号を表示すると、プライバシー漏洩を防ぐために中央の 4 桁が隠されて、「158****9119」と表示されます。

  3. [必須] ユーザーが入力する SQL パラメーターは、SQL インジェクションを防止し、
    文字列スプライシング SQL によるデータベースへのアクセスを禁止するために、パラメーター バインディングまたは METADATA フィールド値によって厳密に制限する必要があります。

  4. [必須] ユーザーによって渡されたパラメータは有効であるかどうかを検証する必要があります。
    注: パラメータの検証を無視すると、次のような問題が発生する可能性があります。
    過剰なページ サイズによるメモリ オーバーフローの発生
    データベース クエリの遅延を引き起こすことによる悪意のある命令 任意
    のリダイレクト
    SQL インジェクション
    逆シリアル化インジェクション
    通常の入力ソース文字列 サービス拒否 ReDoS
    説明: Java コードは正規表現を使用してクライアント入力を検証します。メソッドの記述では通常のユーザー入力の検証には問題ありません
    が、攻撃者が検証のために特別に作成した文字列を使用すると、無限ループにつながる可能性があります。

  5. 【必須】セキュリティフィルタがかかっていない、または適切にエスケープされていないユーザーデータをHTMLページに出力することを禁止します。

  6. [必須] フォームと AJAX の送信には、CSRF セキュリティ フィルタリングを実装する必要があります。
    説明: CSRF (クロスサイト リクエスト フォージェリ) は、一般的なプログラミングの脆弱性です。CSRF 脆弱性のあるアプリケーション/Web サイトの場合
    、攻撃者は事前に URL を構築することができ、被害ユーザーがアクセスするとすぐに、
    ユーザーの知らないうちにバックグラウンドによってデータベース内のユーザー パラメータが変更されます。

  7. [必須] テキスト メッセージ、電子メール、電話、注文、支払いなどのプラットフォーム リソースを使用する場合、乱用や損失を避けるために、数量制限、疲労制御、確認コードの検証などの正しいリプレイ防止制限を実装する必要があります
    。資金の。
    注: 登録中に確認コードが携帯電話に送信される場合、数と頻度に制限がない場合、この機能は他のユーザーに嫌がらせをするために使用され、
    SMS プラットフォームのリソースを浪費する可能性があります。

  8. [推奨事項] 投稿、コメント、インスタント メッセージの送信などのユーザー作成コンテンツが、
    テキスト コンテンツ内の禁止用語のアンチブラッシングやフィルタリングなどのリスク管理戦略を実装する必要があるシナリオ。

5.MySQLデータベース

(1) テーブル作成プロトコル

  1. [必須] はいまたはいいえの概念を表すフィールドは is_xxx 方式で名前を付ける必要があり、データ型は unsigned tinyint
    (1 ははい、0 はいいえを意味します) です。
    注: 負でない数値の場合、フィールドは符号なしである必要があります。
    正例:論理削除を表すフィールド名は_deletedで、1は削除、0は削除なしを意味します。

  2. [必須] テーブル名とフィールド名には小文字または数字を使用する必要があります。数字で始めることは禁止されており、2 つのアンダースコアの間に数字のみを入れることは禁止されています
    データベースのフィールド名の変更は、プレリリースが不可能なため非常にコストがかかり、そのためフィールド名を慎重に検討する必要があります。
    注: MySQL は Windows では大文字と小文字が区別されませんが、Linux ではデフォルトで大文字と小文字が区別されます。したがって、不必要な複雑化を避けるために、データベース名、テーブル名、フィールド名には大文字を使用できません

    正例: aliyun_admin, rdc_config, level3_name
    反例: AliyunAdmin, rdcConfig, level_3_name

  3. [必須] テーブル名に複数の名詞を使用しないでください。
    注: テーブル名はテーブル内のエンティティの内容のみを表す必要があり、エンティティの数を表すべきではありません。対応する DO クラス名も単数形であり、式規則に準拠しています

  4. [必須] desc、range、match、delayed などの予約語を無効にします。MySQL 公式の予約語を参照してください。

  5. [必須] 主キーのインデックス名は pk_field 名、一意のインデックス名は uk_field 名、共通のインデックス名は idx_field name です。
    注: pk_ は主キー、uk_ は一意のキー、idx_ はインデックスの省略形です。

  6. [必須] 10進数型は10進数で、float、doubleは禁止です。
    注: float と double を格納するときに精度が失われるという問題があり、値を比較するときに
    誤った結果が得られる可能性があります。保存されるデータの範囲が小数の範囲を超える場合は、データを整数と小数に分割して別々に保存することをお勧めします。

  7. 【必須】格納する文字列の長さがほぼ等しい場合は、固定長文字列型charを使用してください。

  8. [必須] varchar は可変長の文字列です。事前に割り当てられる記憶領域はありません。長さは 5000 を超えてはなりません。記憶
    領域の他のフィールドのインデックス作成
    効率への影響を避けるために対応する主キー。

  9. [必須] テーブルには、id、gmt_create、gmt_modified の 3 つのフィールドが必要です。
    注: ID は主キーである必要があり、型は符号なし bigint、単一テーブルの自動インクリメント、ステップ サイズは 1 です。gmt_create と
    gmt_modified の型はどちらも date_time 型で、前者は現在形での能動的作成を表し、後者の過去分詞は受動的
    更新を表します。

  10. 【推奨】テーブル名は「業務名_テーブルの機能」とするのがベストです。
    正例: alipay_task / force_project / trade_config

5.MySQLデータベース

(1) テーブル作成プロトコル

  1. [必須] はいまたはいいえの概念を表すフィールドは is_xxx 方式で名前を付ける必要があり、データ型は unsigned tinyint
    (1 ははい、0 はいいえを意味します) です。
    注: 負でない数値の場合、フィールドは符号なしである必要があります。
    正例: 表达逻辑删除的字段名 is_deleted, 1 表示删除, 0 表示未删除。

  2. [必須] テーブル名とフィールド名には小文字または数字を使用する必要があります。数字で始めることは禁止されており、2 つのアンダースコアの間に数字のみを入れることは禁止されています
    データベースのフィールド名の変更は、プレリリースが不可能なため非常にコストがかかり、そのためフィールド名を慎重に検討する必要があります。
    注: MySQL は Windows では大文字と小文字が区別されませんが、Linux ではデフォルトで大文字と小文字が区別されます。したがって、不必要な複雑化を避けるために、データベース名、テーブル名、フィールド名には大文字を使用できません

    正例: aliyun_admin, rdc_config, level3_name
    反例: AliyunAdmin, rdcConfig, level_3_name

  3. [必須] テーブル名に複数の名詞を使用しないでください。
    注: テーブル名はテーブル内のエンティティの内容のみを表す必要があり、エンティティの数を表すべきではありません。対応する DO クラス名も単数形であり、式規則に準拠しています

  4. [必須] desc、range、match、delayed などの予約語を無効にします。MySQL 公式の予約語を参照してください。

  5. [必須] 主キーのインデックス名は pk_field 名、一意のインデックス名は uk_field 名、共通のインデックス名は idx_field name です。
    注: pk_ は主キー、uk_ は一意のキー、idx_ はインデックスの省略形です。

  6. [必須] 10進数型は10進数で、float、doubleは禁止です。
    注: float と double を格納するときに精度が失われるという問題があり、値を比較するときに
    誤った結果が得られる可能性があります。保存されるデータの範囲が小数の範囲を超える場合は、データを整数と小数に分割して別々に保存することをお勧めします。

  7. 【必須】格納する文字列の長さがほぼ等しい場合は、固定長文字列型charを使用してください。

  8. [必須] varchar は可変長の文字列です。事前に割り当てられる記憶領域はありません。長さは 5000 を超えてはなりません。記憶
    領域の他のフィールドのインデックス作成
    効率への影響を避けるために対応する主キー。

  9. [必須] テーブルには、id、gmt_create、gmt_modified の 3 つのフィールドが必要です。
    注: ID は主キーである必要があり、型は符号なし bigint、単一テーブルの自動インクリメント、ステップ サイズは 1 です。gmt_create と
    gmt_modified の型はどちらも date_time 型で、前者は現在形での能動的作成を表し、後者の過去分詞は受動的
    更新を表します。

  10. 【推奨】テーブル名は「業務名_テーブルの機能」とするのがベストです。
    正例: alipay_task / force_project / trade_config

(2) インデックスプロトコル

  1. [必須] 固有のビジネス特性を持つフィールドは、複数のフィールドの組み合わせであっても、一意のインデックスに構築する必要があります。
    注: 一意のインデックスが挿入速度に影響するとは考えないでください。この速度低下は無視できますが、検索速度の向上は
    明らかですアプリケーション層で非常に完全な検証制御が行われたとしても、一意のインデックスはなく、マーフィーの法則に従って
    ダーティ データが生成される必要があります。

  2. 【必須】3テーブル以上の結合は禁止します。結合する必要があるフィールドのデータ型は完全に一貫している必要があり、複数のテーブルに関連するクエリを実行する場合は、
    関連するフィールドにインデックスが必要であることが保証されます。
    注: 2 つのテーブルを結合する場合でも、テーブルのインデックスと SQL のパフォーマンスに注意を払う必要があります。

  3. [必須] varchar フィールドにインデックスを作成するときは、インデックスの長さを指定する必要があります。フィールド全体にインデックスを付ける必要はありません。インデックスの長さは、
    実際のテキストの区別に基づいて決定できます。
    注意: インデックスの長さと識別は一対の矛盾です。一般に、文字列型データの場合、長さ 20 のインデックスは 90% 以上の識別を持ちます。 count(distinct left(column name,index length) を使用できます。 )/ count(*)の判別を
    決定します。

  4. 【必須】ページ内検索では左ボカシ・全ボカシは厳禁ですので、必要に応じて検索エンジンを使用して解決してください。
    注意: インデックスファイルはB-Treeの左端のプレフィックスマッチング機能を持っており、左端の値が不定の場合、このインデックスは使用できません

  5. 【推奨事項】 シナリオ別の注文がある場合は、インデックスの順序性にご注意ください。order by の最後のフィールドは
    結合インデックスの一部であり、file_sort の状況を回避し、クエリのパフォーマンスに影響を与えるために、インデックス結合順序の最後に配置されます。
    正例: where a=? and b=? order by c; 索引: a_b_c
    反例: 索引中有范围查找,那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

  6. [推奨] テーブルが返されるのを避けるために、カバリング インデックスを使用してクエリ操作を実行します。
    説明: 本で第 11 章のタイトルを知る必要がある場合、第 11 章に対応するページが開きますか? ディレクトリを参照するだけです
    。このディレクトリはカバーインデックスとして機能します。
    正例: 能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种 效果,用 explain 的结果, extra 列会出现: using index。

  7. [推奨] 遅延相関またはサブクエリを使用して、複数ページのページング シナリオを最適化します。
    注: MySQL はオフセット行をスキップしませんが、オフセット + N 行を取得し、あきらめる前にオフセット行を返し、
    N 行を返します。オフセットが特に大きい場合、効率が非常に低くなるか、返されるページの総数が減少します。を制御するか、
    一定のしきい値を超えたページ数に対して SQL リライトを実行する必要があります。
    正例: 先快速定位需要获取的 id 段,然后再关联: SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

  8. [推奨事項] SQL パフォーマンス最適化の目標: 少なくとも range レベルに達すること。要件は ref レベルであり、const にできればそれが
    最善です。
    注:
    1) 単一の consts テーブルには一致する行 (主キーまたは一意のインデックス) が最大 1 つあり、最適化フェーズ中にデータを読み取ることができます。
    2) ref は、通常のインデックスの使用を指します。
    3) range はインデックスに対して範囲検索を実行します。
    反例:Explain 表 type=index の結果は、索引物理ファイルの完全スキャンですが、これは非常に低速です。この索引レベルは
    範囲よりも低く、完全表スキャンに比べれば小さく見えます。

  9. 【推奨】複合インデックスを作成する場合、最も差別化度の高いインデックスが一番左にあります。
    正例: a=? および b=? の場合、列 a がほぼ一意の値に近い場合、idx_a インデックスのみを構築する必要があります

    注: 不等号と等号の判定条件が混在する場合は、インデクスを作成する際に等号条件の列を前に置いてください。例: ここで、a>?
    および b=? この場合、a の区別性が高い場合でも、b をインデックスの先頭に配置する必要があります。

  10. [推奨事項] 異なるフィールド型によって引き起こされる暗黙的な変換が原因でインデックスエラーが発生するのを防ぎます。

  11. 【参考】 指数を作成する際には、次のような極端な誤解を避けてください。
    1) 不足するよりも過剰な方が良い。クエリにはインデックスが必要であると考えられています。
    2) 多すぎるよりは少ない方が良いです。インデックスはスペースを消費し、更新や新規追加の速度を大幅に低下させると考えられています。
    3) 一意のインデックスに抵抗します。ビジネスの独自性は、「最初にチェックしてから挿入する」方法を通じてアプリケーション層で解決する必要があると考えられています。

(3) SQL文

  1. [必須] count( ) の代わりに count (列名) または count (定数) を使用しないでください。 count( ) はSQL92 で定義された
    行をカウントするための標準構文です。データベースとは何の関係もありません。 NULL と非 NULL を使用します。
    注: count(*) は NULL 値を持つ行をカウントしますが、count(column name) はこの列内の NULL 値を持つ行をカウントしません。


  2. [必須] count(distinctcol) NULL を除くこの列の一意の行の数をカウントします。一方の列がすべて NULL の場合、他の列の値が異なる場合でも、count(distinctcol1,col2) は 0 を返すことに注意してください

  3. 【必須】あるカラムの値が全てNULLの場合、count(col)の戻り結果は0ですが、sum(col)の戻り結果はNULLとなるため、NPE問題に注意する必要があります。 sum() を使用します

    良い例: 次のメソッドを使用すると、合計の NPE 問題を回避できます。 SELECT IF(ISNULL(SUM(g)),0,SUM(g))
    FROM table;

  4. [必須] ISNULL() を使用して、NULL 値かどうかを判断します。
    説明: NULL と任意の値を直接比較すると、NULL になります。
    1) NULL<>NULL の戻り結果は false ではなく NULL です。
    2) NULL=NULL の戻り結果は NULL であり、true ではありません。
    3) NULL<>1 の戻り結果は NULL であり、true ではありません。

  5. [必須] コードでページング クエリ ロジックを記述する場合、count が 0 の場合は、後続のページング ステートメントの実行を避けるために、それを直接返す必要があります。

  6. [必須] 外部キーとカスケードは使用できません。すべての外部キーの概念はアプリケーション層で解決する必要があります。
    注: 学生と成績の関係を例に挙げると、学生テーブルの Student_id は主キーであり、成績テーブルの Student_id は
    外部キーです。Student テーブルの Student_id を更新し、同時に成績テーブルの Student_id の更新をトリガーすると、それは
    カスケード更新となります。外部キーとカスケード更新は、単一マシンでの同時実行性が低い場合には適していますが、分散クラスターや同時性が高いクラスターには適していません。カスケード更新は強力にブロックされ、データベース更新ストームのリスクがあります。外部キーはデータベースの挿入速度に影響します
    。 。

  7. 【必須】ストアドプロシージャの使用は禁止されており、ストアドプロシージャはデバッグや拡張が難しく、移植性がありません。

  8. 【必須】データの修正やレコードの削除・変更を行う場合は、誤って削除しないように最初に選択し、
    正しいことを確認してから更新文を実行する必要があります。

  9. 【推奨】 in操作が回避できる場合は回避し、回避できない場合はin以降のコレクション要素数を慎重に評価し、
    1,000以内に制御する必要があります。

  10. [参考] グローバル化の必要がある場合、文字の格納および表現はすべてUTF-8でエンコードされますが、
    文字の統計関数の違いに注意してください。
    説明:
    SELECT LENGTH ("Easy Work"); 12 を返します
    SELECT CHARACTER_LENGTH ("Easy Work"); 4 を返し
    ます 式を保存する必要がある場合は、保存用に utfmb4 を選択し、utf-8 エンコーディングとの違いに注意してください。

  11. [参考] TRUNCATE TABLE は DELETE よりも高速で、システム リソースやトランザクション ログ リソースの使用量も少なくなりますが、TRUNCATE は
    トランザクションがなく、トリガーが発生しないため、事故を引き起こす可能性があるため、開発コードでの使用は推奨されません。
    説明: TRUNCATE TABLE は、WHERE 句のない DELETE ステートメントと機能的には同じです。

(4) ORMマッピング

  1. [必須] テーブル クエリでは、クエリのフィールド リストとして * を使用しないでください。どのフィールドが必須であるかを明確に記述する必要があります。
    説明: 1) クエリ アナライザーの解析コストが増加します。2) フィールドの追加または削除は、resultMap 構成と矛盾する可能性があります。

  2. [必須] POJO クラスのブール属性は is で追加できませんが、データベース フィールドは is_ で追加する必要があります。これには、 resultMap の
    フィールドと属性間のマッピングが必要です。
    说明: 参见定义 POJO 类以及数据库字段定义规定,在<resultMap>中增加映射,是必须的。 在 MyBatis Generator 生成的代码中,需要进行对应的修改。

  3. [必須] 戻りパラメータとして resultClass を使用しないでください。すべてのクラス属性名がデータベース フィールドに対応する場合でも、定義する必要があります
    。逆に、各テーブルにはそれに対応するものが必要です。
    説明: メンテナンスを容易にするために、フィールドを DO クラスから分離するようにマッピング関係を構成します。

  4. [必須] sql.xml 構成パラメータを使用します: #{}、#param# ${} は使用しないでください。この方法は SQL インジェクションが発生しやすいです。

  5. [必須] iBATIS に付属の queryForList(String statementName, int start, int size) は推奨されません

    注: 実装方法は、データベース内のstatementNameに対応するSQL文のレコードをすべて取得し、
    subListでstartとsizeのサブセットを取得します。
    正の例: Map<String, Object> map = new HashMap<String, Object>();
    map.put(“start”, start);
    map.put(“size”, size);

  6. [必須] HashMap および Hashtable をクエリ結果セットの出力として直接使用することはできません。
    注: resultClass="Hashtable" はフィールド名と属性値を挿入しますが、値の型は制御できません。

  7. [必須] データテーブルレコードを更新する場合、レコードの対応する gmt_modified フィールド値も現在時刻に更新する必要があります。

  8. [推奨事項] 大規模で包括的なデータ更新インターフェイスを作成しないでください。POJO クラスとして渡された場合は、自身の対象更新フィールドであるかどうかに関係なく
    、テーブルセット c1=value1,c2=value2,c3=value3; を更新します。これは誤りです。SQL を実行するときは
    、変更されていないフィールドを更新しないでください。第一に、エラーが発生しやすくなり、第二に、非効率になり、第三に、バイナリ ログ ストレージが増加します。

  9. 【参考】@Transactionalトランザクションを悪用しないでください。トランザクションはデータベースの QPS に影響します。また、トランザクションが使用される場合は、
    キャッシュ ロールバック、検索エンジンのロールバック、メッセージ補正、統計補正などのさまざまなロールバック ソリューションを考慮する必要があります。

  10. 【参考】 <isEqual>中的 compareValue 是与属性值对比的常量,一般是数字,表示相等时带 上此条件; <isNotEmpty>表示不为空且不为 null 时执行; <isNotNull>表示不为 null 值时 执行。

6. エンジニアリング体制

(1) アプリケーションの階層化

  1. [推奨] デフォルトでは、図の上位層は下位層に依存しており、矢印の関係は直接の依存関係を示しています。たとえば、オープン インターフェイス層は Web 層に依存することも、サービス層に直接依存することもできます
    。など:
    ここに画像の説明を挿入します
    オープンインターフェイス層: Service メソッドを直接カプセル化可能 RPC インターフェイスとして公開; Web 経由で http インターフェイスにカプセル化;
    ゲートウェイのセキュリティ制御、フロー制御などを実行します。
    端末表示レイヤー:各端末のテンプレート レンダリングおよび表示レイヤー。現在の主なものは、ベロシティレンダリング、JSレンダリング、JSPレンダリング、モバイルディスプレイなどです。
    Web 層:主にアクセス制御の転送、さまざまな基本パラメータの検証、または非再利用サービスの単純な処理など。
    サービス層:比較的特殊なビジネス ロジック サービス層。
    マネージャー層:以下の特徴を持つ一般的なビジネス処理層:
    1) サードパーティのプラットフォームをカプセル化し、戻り結果の前処理と例外情報の変換を行う層;
    2) キャッシュ ソリューションや一般的なミドルウェアなど、サービス層の一般的な機能のシンク処理;
    3) DAO 層と対話し、複数の DAO の組み合わせを再利用します。
    DAO レイヤー:データ アクセス レイヤー。基盤となる MySQL、Oracle、Hbase などとデータをやり取りします。
    外部インターフェイスまたはサードパーティ プラットフォーム:他の部門の RPC オープン インターフェイス、基本プラットフォーム、および他社の HTTP インターフェイスを含みます。

  2. 【参考】(階層型例外処理プロトコル) DAO層では多くの種類の例外が発生しますが、細かい例外をキャッチすることは不可能ですので、catch(Exception e)メソッドを使用し、出力せずにnew DAOException(e)をスローしてください

    ログ: ログはマネージャー/サービス層で取得してログ ファイルに書き込む必要があるため、同じサーバーが
    再度ログを書き込むと、パフォーマンスとストレージが無駄になります。サービス層で例外が発生した場合には、エラーログをディスクに記録し、
    パラメータ情報も可能な限り含める必要があり、これは犯罪現場を守ることに等しい。Manager 層と Service が同じマシンにデプロイされている場合、ログの処理方法は
    DAO 層の処理と一致し、別々にデプロイされている場合、ログの処理方法は Service と一致します。Web 層は、
    すでに最上位レベルにあるため、上向きに例外をスローし続けることはできません。この例外によりページが正常に表示されなくなることに気付いた場合は、わかりやすいエラー ページに直接ジャンプして、エラー メッセージを追加する必要があります
    。それはユーザーにとって理解しやすいことです。オープン インターフェイス層は例外を処理し、それらをエラー コード
    およびエラー メッセージとして返す必要があります。

  3. 【参考】階層ドメインモデル仕様:
    DO(Data Object):データベースのテーブル構造と1対1に対応し、DAO層を介してデータソースオブジェクトを上方向に伝送します。
    DTO (Data Transfer Object):データ転送オブジェクト。サービスまたはマネージャーによって転送されるオブジェクト。
    BO (ビジネスオブジェクト):ビジネスオブジェクト。サービス層によって出力されるビジネス ロジックをカプセル化するオブジェクト。
    AO (アプリケーション オブジェクト):アプリケーション オブジェクト。Web 層とサービス層の間の抽象再利用オブジェクト モデルは、
    プレゼンテーション層に非常に近く、再利用性が低いです。
    VO (ビュー オブジェクト):表示レイヤー オブジェクト。通常は、Web によってテンプレート レンダリング エンジン レイヤに送信されるオブジェクトです。
    **クエリ:** データ クエリ オブジェクト。各レイヤーは上位レイヤーからクエリ リクエストを受け取ります。
    3 つ以上のパラメーターを含むクエリのカプセル化では、送信に Map クラスを使用することは禁止されていることに注意してください。

(2) セカンドパーティライブラリの依存関係

  1. [必須] 次のルールに準拠するように GAV を定義します。
    1) GroupID 形式: com.{会社/BU}.Business Line.[Sub-Business Line]、最大 4 レベル。
    説明: {会社/BU} 例: alibaba/taobao/tmall/aliexpress など BU レベル 1、サブビジネス ラインはオプションです。
    正例: com.taobao.jstorm 或 com.alibaba.dubbo.register
    2) ArtifactID 形式: 製品ライン名 - モジュール名。セマンティクスが繰り返されたり省略されたりすることはありません。まず中央倉庫に行って確認してください。
    正例: dubbo-client / fastjson-api / jstorm-tool
    3) バージョン: 詳細な規定については、以下を参照してください。

  2. 【必須】 セカンドパーティライブラリのバージョン番号の命名方法: メジャーバージョン番号. マイナーバージョン番号. リビジョン番号
    1) メジャーバージョン番号: 製品の方向性変更、または大規模 API の非互換、またはアーキテクチャのアップグレード非互換。
    2) マイナー バージョン番号: 相対的な互換性を維持し、主要な機能を追加し、API の互換性のない変更への影響を最小限に抑えます。
    3) リビジョン番号: 完全な互換性の維持、バグの修正、マイナーな機能の追加など。
    注: 開始バージョン番号は 0.0.1 ではなく 1.0.0 である必要があることに注意してください。正式にリリースされたクラス ライブラリは、バージョン番号が
    連続性を持つように、検証のためにまず中央倉庫に移動する必要があります。公式バージョン番号は許可されていません。上書きされてアップグレードされます。たとえば、現在のバージョン: 1.3.3、次に
    適切なバージョン番号: 1.3.4、1.4.0、または 2.0.0

  3. [必須] オンライン アプリケーションは SNAPSHOT バージョンに依存しません (セキュリティ パッケージを除く)。
    注: SNAPSHOT バージョンに依存しないことで、アプリケーションのリリースの冪等性が保証されます。さらに、コンパイル時のパッケージ化と構築も高速化できます。

  4. [必須] セカンドパーティ ライブラリを追加またはアップグレードすると、ファンクション ポイントを除く他の jar パッケージの調停結果は変更されません。変更がある場合は、
    明確に評価および検証する必要があります。dependency:resolve の前後の情報を比較することをお勧めします。調停結果が完全に一致しない場合は、dependency:tree コマンドを使用して相違点を見つけ、jar パッケージを除外し
    ます。


  5. [必須] セカンドパーティのライブラリでは列挙型を定義でき、パラメータでは列挙型を使用できますが、インターフェイスの戻り値では列挙型または列挙型を含む POJO オブジェクトの使用は許可されません。

  6. [必須] セカンドパーティのライブラリ グループに依存する場合、バージョン番号の不一致を避けるために、統合バージョン変数を定義する必要があります。注: Springframework-core、-context、および -beans に依存します。これらはすべて同じバージョンです。バージョンを保存する変数を
    定義できます: ${spring.version}。依存関係を定義するときは、このバージョンを参照してください。


  7. [必須]サブプロジェクトの pom 依存関係で、同じ GroupId、同じ ArtifactId、ただし異なるバージョンを持つことは禁止されています。
    注: ローカルでデバッグする場合、各サブプロジェクトで指定されたバージョン番号が使用されますが、war にマージされる場合、
    最終的な lib ディレクトリに表示できるバージョン番号は 1 つだけです。オフラインでのデバッグは正しくても、オンラインでリリースすると問題が発生するという問題があるかもしれません。

  8. 【推薦する】所有 pom 文件中的依赖声明放在<dependencies>语句块中,所有版本仲裁放在 <dependencyManagement>语句块中。 说明: <dependencyManagement>里只是声明版本,并不实现引入,因此子项目需要显式的声 明依赖, version 和 scope 都读取自父 pom。而<dependencies>所有声明在主 pom 的 <dependencies>里的依赖都会自动引入,并默认被所有的子项目继承。

  9. [推奨事項] セカンドパーティのライブラリには構成項目を含めるべきではなく、少なくともこれ以上構成項目を追加しないでください。

  10. [参考] セカンドパーティ ライブラリを適用する際に依存関係の競合を回避するために、セカンドパーティ ライブラリの発行者は次の原則に従う必要があります。
    1) 単純さと制御性の原則。
    サービス API、必要なドメイン モデル オブジェクト、Utils クラス、定数、列挙などのみを含む、不要な API と依存関係をすべて削除します。他のセカンド パーティ ライブラリに依存する場合は、提供されているとおりにそれらを導入して、セカンド パーティ ライブラリのユーザーが特定のバージョン番号に依存できるようにしてください。ログの
    特定の実装はなく、ログ フレームワークのみに依存します。
    2) 安定したトレーサビリティの原則。各バージョンの変更を記録する必要があり、誰がセカンド パーティ ライブラリを保守しているか、ソース コードがどこにあるか、すべてに
    簡単にアクセスできる必要があります。ユーザーが積極的にバージョンをアップグレードしない限り、パブリックのセカンドパーティ ライブラリの動作は変更されるべきではありません。

(3) サーバー

  1. [推奨事項] 同時実行性の高いサーバーの場合、TCP プロトコルの time_wait タイムアウトを減らすことを推奨します。注: デフォルトでは、オペレーティング システムは 240 秒後に time_wait 状態の接続を閉じます。同時アクセスが多い場合、 time_wait の接続が多すぎるため、
    サーバーは新しい接続を確立できない場合があるため、これを減らす必要があります。待機値。


    正例: 在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒) : net.ipv4.tcp_fin_timeout = 30

  2. [推奨] サーバーがサポートするファイル ハンドル (ファイル ディスクリプタ、略称 fd) の最大数を増やします。
    注: 主流のオペレーティング システムの設計では、TCP/UDP 接続をファイルと同じ方法で管理します。つまり、1 つの接続が
    1 つの fd に対応します。
    メインストリーム Linux サーバーがサポートする fd の最大数はデフォルトで 1024 です。同時接続数が多いと、 fds 不足により「ファイルが多すぎます」エラーが発生しやすくなり、新しい接続の確立に失敗します。Linuxサーバー
    でサポートされるハンドルの最大数を数倍に増やすことをお勧めします (サーバーのメモリ量に関連します)。

  3. [推奨] -XX:+HeapDumpOnOutOfMemoryError パラメーターを JVM に設定して、
    OOM シナリオが発生したときに JVM がダンプ情報を出力できるようにします。
    注: OOM は確率的に発生し、数か月ごとに定期的に発生する場合もあるため、発生時のオンサイト情報は
    トラブルシューティングに非常に役立ちます。

  4. [推奨事項] オンライン運用環境では、 GC後のヒープサイズ調整による
    負荷を避けるため、JVMのXmsとXmxのメモリ容量を同じサイズに設定してください。

  5. [参考] サーバーの内部リダイレクトにはフォワードを使用します。外部リダイレクト アドレスを生成するには URL アセンブリ ツール クラスを使用します。そうしないと、
    URL のメンテナンスに不整合が発生し、潜在的なセキュリティ リスクが発生します。

7. 固有名詞の説明

  1. POJO
    (Plain Ordinary Java Object): このマニュアルでは、POJOは、DO/DTO/BO/VO などを含む、setter/getter/toString のみを持つ単純なクラスを特に指します。
  2. GAV (GroupId、ArtifactctId、Version): jar パッケージを一意に識別するために使用される Maven 座標。
  3. OOP (オブジェクト指向プログラミング): このマニュアルでは、一般にクラスとオブジェクトのプログラミング方法について言及します。
  4. ORM (オブジェクト リレーショナル マッピング): オブジェクト リレーショナル マッピング、オブジェクト ドメイン モデルと基礎となるデータ間の変換
    この記事では、一般に iBATIS、mybatis、およびその他のフレームワークについて言及します。
  5. NPE (java.lang.NullPointerException): Null ポインタ例外。
  6. SOA (Service-Oriented Architecture):
    疎結合された粗粒なアプリケーションコンポーネントをニーズに応じてネットワーク経由で分散、組み合わせ、利用することができ、コンポーネントの再利用性や保守性の向上に役立つサービス指向アーキテクチャ。
  7. ワンパーティ ライブラリ:このプロジェクトの内部サブプロジェクト モジュールが依存するライブラリ (jar パッケージ)。
  8. セカンドパーティ ライブラリ:企業内部で中央倉庫に公開され、企業内の他のアプリケーションから利用できるライブラリ (jar パッケージ)。
  9. サードパーティ ライブラリ:社外のオープン ソース ライブラリ (jar パッケージ)。
  10. IDE (統合開発環境): プログラム開発環境を提供するために使用されるアプリケーションで、一般に
    コード エディター、コンパイラー、デバッガー、グラフィカル ユーザー インターフェイスなどのツールが含まれます。この「マニュアル」では、一般的に IntelliJ IDEA
    および eclipse を指します。

おすすめ

転載: blog.csdn.net/qq_42666609/article/details/131912037