1. [必須] コード内の名前は、アンダースコアまたはドル記号で始めることはできません。また、アンダースコアまたはドル記号で終わることもできません。
対抗例: _nam / __name / $Object / name_ / name$ / Object$
2. 【必須】コード内でのネーミングにピンインと英語を混ぜて使用することは厳禁です。直接中国人。
注:英語のスペルと文法を正しくすると、読者が理解しやすくなり、曖昧さを避けることができます。たとえ純粋なピンインによる名前付けも避けるべきであることに注意してください。
反例:DaZhePromotion [割引] / getPingfenByName() [評価] / int ある変数 = 3
正の例: alibaba / taobao / youku / Hangzhou などの国際名は英語と同じとみなせます。
3. [必須] クラス名は UpperCamelCase スタイルを使用し、次の例外を除いてキャメル ケースに従う必要があります: (ドメイン モデルの関連する命名) DO / BO / DTO / VO など。
良い例: MarcoPolo / UserDO / CamelCase に従う必要があります。
肯定的な例: localValue / getHttpMessage() / inputUserId
5. [必須] 定数名はすべて大文字にする必要があり、単語はアンダースコアで区切る必要があり、完全かつ明確な意味を表現するように努め、名前を考えないようにしてください。長すぎます。
正の例: MAX_STOCK_COUNT
6. [必須] 抽象クラス名は Abstract または Base で始まり、テスト クラス名は対象となるクラスの名前で始まります。テストし、テストで終了します。
7. [必須] 角括弧は配列型の一部です: String[] args;
Counter の例: String args[] を使用して定義しないでください。
8. [必須] POJO クラスのブール型変数に is を追加しないでください。追加しないと、一部のフレームワーク解析でシリアル化エラーが発生します。
反例: 基本データ型として定義された属性は isSuccess であり、そのメソッドも isSuccess() です。RPC フレームワークは逆解析を実行するときに、対応する属性名が success であると「認識」し、その結果、属性は無効になります。を取得した後、例外が発生しました。
9. [必須] パッケージ名には小文字を使用する必要があり、ドット区切り文字の間に自然な意味を持つ英単語が 1 つだけ存在する必要があります。パッケージ名は常に単数形を使用しますが、クラス名に複数の意味がある場合は、クラス名に複数形を使用できます。
良い例: アプリケーション ツール クラスのパッケージ名は com.alibaba.open.util、クラス名は MessageUtils (このルールは Spring Framework 構造を参照します)
10. [必須] 完全に非標準的な略語は避けてください。文章の意味を混乱させる。
カウンターの例: AbstractClass の「省略形」は AbsClass という名前であり、条件の「省略形」は condi という名前です。このような任意の省略形は、コードの可読性を著しく低下させます。
11. [推奨事項] デザインパターンを使用する場合は、クラス名に特定のパターンを反映することをお勧めします。
注: 名前にデザインパターンを反映させると、読者が建築デザインのアイデアをすぐに理解できるようになります。
12. [推奨事項] インターフェースクラスのメソッドとプロパティには修飾子を追加しないでください(publicも追加しないでください)。コードの単純なプロパティを維持し、有効な Javadoc コメントを追加します。インターフェイスでは変数を定義しないようにしてください。変数を定義する必要がある場合、変数はインターフェイス メソッドに関連しており、アプリケーション全体の基本定数である必要があります。
正の例: インターフェースメソッドの署名: void f(); インターフェースの基本定数表現: String COMPANY = "alibaba";
13. インターフェイスと実装クラスの命名には 2 つのルールがあります:
1) [必須] Service クラスと DAO クラスの場合、SOA の概念に基づいて、公開されるサービスはインターフェイスである必要があり、内部実装クラスはImpl サフィックスとインターフェイスの違い。
14. [参考] 列挙型クラス名には接尾辞 Enum を付けることを推奨します。列挙型メンバーの名前はすべて大文字で、単語はアンダースコアで区切る必要があります。
注: Enumeration は実際には特別な定数クラスであり、コンストラクターはデフォルトで強制的にプライベートになります。
15. 【参考】各レイヤの命名規則:
A)サービス/DAOレイヤメソッドの命名規則
6) 変更方法には先頭に update が付きます。
B) ドメインモデルの命名規則
1) データオブジェクト: xxxDO、xxx はデータテーブルの名前です。
2)データ転送オブジェクト:xxxDTO、xxxは業務分野に関連する名前です。
3) 表示オブジェクト: xxxVO、xxx は一般に Web ページの名前です。
4) POJO は DO/DTO/BO/VO の総称であり、xxxPOJO という名前を付けることは禁止されています。
1. [必須] マジック値(未定義の定数)をコード内に直接記述することはできません。
カウンターの例: String key="Id#taabao_"+tradeId;
cache.put(key, value);
2. [必須] long または Long に最初に値が割り当てられる場合は、大文字の L を使用する必要があります。小文字の l 、小文字は数字の 1 と混同されやすく、誤解を引き起こします。
説明: Long a = 2l; 数値 21 として記述されますか?
3. すべての定数を維持するために 1 つの定数クラスを使用しないでください。それらは定数関数に従って分類され、個別に維持される必要があります。 。たとえば、キャッシュ関連の定数はクラス CacheConsts に配置され、システム構成関連の定数はクラス ConfigConsts に配置されます。
注: 大規模で包括的な定数クラスの場合、変更された定数を見つけるには検索機能を使用する必要があり、理解と保守には役立ちません。
4. [推奨] 定数の再利用には、アプリケーション間の共有定数、アプリケーション内の共有定数、サブプロジェクト内の共有定数、パッケージ内の共有定数、クラス内の共有定数の 5 つのレベルがあります。
1) アプリケーション間の共有定数: セカンドパーティのライブラリに配置され、通常は client.jar の定数ディレクトリに配置されます。
2) アプリケーション内共有定数: ライブラリのモジュール内の定数ディレクトリに配置されます。
反例: わかりやすい変数も、アプリケーション内で共有定数として統一的に定義する必要があります。2 つのシージマスターは、2 つのクラスで「はい」を表す変数を定義しました:
クラス A: public static Final String YES = " yes";
class B: public static Final String YES = "y"; A.YES.equals(B.YES) では、期待値は true ですが、実際の戻り値は false となり、オンラインで問題が発生します。
3) サブプロジェクト内の共有定数、つまり現在のサブプロジェクトの定数ディレクトリ内。
4) パッケージ内の共有定数: つまり、現在のパッケージの下にある別の定数ディレクトリにあります。
5) クラス内の共有定数: クラス内で直接プライベートな静的な最終定義。
5. [推奨] 変数値が範囲内でのみ変更される場合は、Enum クラスを使用します。名前以外の拡張属性がある場合は、Enum クラスを使用する必要があります。次の例の数字は、曜日を示す拡張情報です。
正の例: public Enum{ MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}
1. [必須] 中括弧の使用に関する規約。中括弧が空の場合は、改行せずに単に {} を記述します。空ではないコード ブロックの場合:
1) 左中括弧の前に改行はありません。
2) 左中括弧の後に改行します。
3) 右中括弧の前で改行します。
4) 右中括弧の後に else コードがある場合、改行は行われません。これは、右中括弧の終了後に行を改行する必要があることを意味します。
2. [必須] 左括弧と次の文字の間にスペースはありません。同様に、右括弧と前の文字の間にはスペースがありません。詳細については、第 5 条の下にある正しいヒントの例を参照してください。
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");// 在右大括号后直接结束,则必须换行 } }
6. 【强制】单行字符数限不超过 120 个,超出需要换行时 个,超出需要换行时 遵循如下原则:
1) 第二行相对一缩进 4个空格,从第三行开始不再继续缩进参考示例。
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);
7. 【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
正例:下例中实参的"a",后边必须要有一个空格。
method("a", "b", "c");
8. 【强制】IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式。
9. 【推荐】没有必要增加若干空格来使某一行的字符与上一行的相应字符对齐。
正例:
int a = 3;long b = 4L;float c = 5F; StringBuffer sb = new StringBuffer();
注: 変数 sb を追加します。整列が必要な場合は、a、b、c にいくつかのスペースを追加する必要があります。変数が多い場合、これは面倒です。
10. [推奨]メソッド本体内の実行文グループ、変数定義文グループ、異なるビジネスロジックまたは異なるセマンティクスの間に空行を挿入します。同じビジネス ロジックとセマンティクスの間に空行を挿入する必要はありません。
注:複数行のスペースを挿入して区切る必要はありません。
1. [必須] クラスのオブジェクト参照を介してこのクラスの静的変数または静的メソッドにアクセスすることは避けてください。クラス名を使用して直接アクセスするだけです。
2. [必須] すべてのオーバーライド メソッドには @Override アノテーションを付ける必要があります。
反例: getObject() と get0object() の問題。 1 つは文字の O で、もう 1 つは数字の 0 です。 @Override を追加すると、オーバーライドが成功したかどうかを正確に判断できます。さらに、メソッド シグネチャが抽象クラスで変更された場合、その実装クラスはすぐにコンパイルしてエラーを報告します。
3. [必須] Java 変数パラメータは、同じパラメータ型および同じビジネス上の意味を持つ場合にのみ使用できます。オブジェクトの使用は避けてください。
注: 変数パラメータはパラメータリストの最後に配置する必要があります。 (学生の皆さんは、変数パラメータのプログラミングをできるだけ避けることをお勧めします)
正の例: public User getUsers(String type, Integer... ids)
4. 原則として、インターフェースのメソッドシグネチャは、インターフェイスの呼び出し元に影響を与えないように、Outside を変更することはできません。インターフェイスが廃止された場合は、 @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 オブジェクトが生成され、この範囲の整数値は == を使用して直接判断できますが、すべてのデータが再利用されます。この範囲外のオブジェクトはヒープ上に生成され、既存のオブジェクトは再利用されません。これは大きな落とし穴です。判断には、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方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
说明:
String str = "a,b,c,,";
String[] ary = str.split(",");
//预期大于3,结果是3
System.out.println(ary.length);
14. 【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读。
15. 【推荐】 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法。 说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为方法信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。
16. 【推荐】setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,尽量不要增加业务逻辑,增加排查问题的难度。
反例:
public Integer getData() {if (true) {return data + 100; } else {return data - 100; } }
17. 【推荐】循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。 反例:
String str = "start";for (int i = 0; i < 100; i++) { str = str + "hello"; }
说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
18. 【推荐】final可提高程序响应效率,声明成final的情况:
1) 不需要重新赋值的变量,包括类属性、局部变量。
2) 对象参数前加final,表示不允许修改引用的指向。
3) 类方法确定不允许被重写。
19. 【推荐】慎用Object的clone方法来拷贝对象。
说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现属性对象的拷贝。
20. 【推荐】类成员与方法访问控制从严:
1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。
2) 工具类不允许有public或default构造方法。
3) 类非static成员变量并且与子类共享,必须是protected。
4) 类非static成员变量并且仅在本类使用,必须是private。
5) 类static成员变量如果仅在本类使用,必须是private。
6) 若是static成员变量,必须考虑是否为final。
7) 类成员方法只供类内部调用,必须是private。
8) 类成员方法只对继承类公开,那么限制为protected。
说明:任何类、方法、参数、变量,严控访问范围。过宽泛的访问范围,不利于模块解耦。
思考:如果是一个private的方法,想删除就删除,可是一个public的Service方法,或者一个public的成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,如果无限制的到处跑,那么你会担心的。
1. 【强制】关于hashCode和equals的处理,遵循如下规则:
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象做为Map的键,那么必须重写hashCode和equals。
正例:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。
2. 【强制】 ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList ;
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
3. 【强制】 在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException 异常。
4. 【强制】使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()。
反例:直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。
正例:
List<String> list = new ArrayList<String>(2); list.add("guan"); list.add("bao"); String[] array = new String[list.size()]; array = list.toArray(array);
说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。
5. 【强制】使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。
说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。 String[] str = new String[] { "a", "b" }; List list = Arrays.asList(str);
第一种情况:list.add("c"); 运行时异常。
第二种情况:str[0]= "gujin"; 那么list.get(0)也会随之修改。
6. 【强制】泛型通配符 extends T>来接收返回的数据,此写法的泛型集合不能使用add方法。
说明:苹果装箱后返回一个 extends Fruits>对象,此对象就不能往里加任何水果,包括苹果。
7. 【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
反例:
List<String> a = new ArrayList<String>(); a.add("1"); a.add("2");for (String temp : a) {if ("1".equals(temp)) { a.remove(temp); } }
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗? 正例:
Iterator<String> it = a.iterator();while (it.hasNext()) { String temp = it.next();if (删除元素的条件) { it.remove(); } }
8. 【强制】 在JDK7版本以上,Comparator要满足自反性,传递性,对称性,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。
说明:
1) 自反性:x,y的比较结果和y,x的比较结果相反。
2) 传递性:x>y,y>z,则x>z。
3) 对称性:x=y,则x,z比较结果和y,z比较结果相同。
反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
new Comparator<Student>() { @Overridepublic int compare(Student o1, Student o2) {return o1.getId() > o2.getId() ? 1 : -1; } }
9. 【推荐】集合初始化时,尽量指定集合初始值大小。 说明:ArrayList尽量使用ArrayList(int initialCapacity) 初始化。
10. 【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。
说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。
正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。
11. 【推荐】高度注意Map类集合K/V能不能存储null值的情况,如下表格:
集合类 | Key | Value | Super | 说明 |
Hashtable | 不允许为null | 不允许为null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为null | 不允许为null | AbstractMap | 分段锁技术 |
TreeMap | 不允许为null | 允许为null | AbstractMap | 线程不安全 |
HashMap | 允许为null | 允许为null | AbstractMap | 线程不安全 |
反例: 由于HashMap的干扰,很多人认为ConcurrentHashMap是可以置入null值,注意存储null值时会抛出NPE异常。
12. 【参考】合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。
说明:稳定性指集合每次遍历的元素次序是一定的。有序性是指遍历的结果是按某种比较规则依次排列的。如:ArrayList是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort。
13. 【参考】利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。
1. 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
说明:资源驱动类、工具类、单例工厂类都需要注意。
2. 【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
正例:
public class TimerTaskThread extends Thread {public TimerTaskThread(){super.setName("TimerTaskThread"); ... }
3. 【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
4. 【强制】线程池不允许使用 Executors去创建,而是通过ThreadPoolExecutor去创建,这样的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
说明: Executors返回的线程池对象的弊端如下 :
1)FixedThreadPool和 SingleThread:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
5. 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() { @Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd"); } }
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。
6. 【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
7. 【强制】对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
说明:线程一需要对表A、B、C依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序也必须是A、B、C,否则可能出现死锁。
8. 【强制】并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据。
说明:如果每次访问冲突概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3次。
9. 【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
10. 【推荐】使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至countDown方法,直到超时才返回结果。
说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。
11. 【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。
说明:Random实例包括java.util.Random 的实例或者 Math.random()实例。
正例:在JDK7之后,可以直接使用API ThreadLocalRandom,在 JDK7之前,可以做到每个线程一个实例。
12. 【推荐】通过双重检查锁(double-checked locking)(在并发场景)实现延迟初始化的优化问题隐患(可参考 The "Double-Checked Locking is Broken" Declaration),推荐问题解决方案中较为简单一种(适用于JDK5及以上版本),将目标属性声明为 volatile型。
反例:
class Foo {private Helper helper = null;public Helper getHelper() {if (helper == null)synchronized (this) {if (helper == null) helper = new Helper(); }return helper; }// other functions and members...}
13. [参考] Volatile はマルチスレッドにおける不可視メモリの問題を解決します。 1 回の書き込みと多数の読み取りの場合、変数の同期の問題は解決できますが、書き込みが多数の場合、スレッドの安全性の問題は解決できません。 count++ 操作の場合は、次のクラスを使用して実装します。 AtomicInteger count = new AtomicInteger(); count.addAndGet(1); JDK8 の場合は、AtomicLong よりもパフォーマンスの良い LongAdder オブジェクトを使用することをお勧めします。 (オプティミスティックロックの再試行回数が減ります)。
14. [参考] HashMap のリサイズ容量が不足している場合、同時実行性が高く、デッドリンクが発生し、CPU の負荷が高くなる可能性がありますので、開発時にはこのリスクを回避するように注意してください。
15. [参考] ThreadLocal では共有オブジェクトの更新問題を解決できません。ThreadLocal オブジェクトには静的変更を使用することをお勧めします。この変数はスレッド内のすべての操作に共通であるため、静的変数として設定されます。このようなすべてのインスタンスはこの静的変数を共有します。つまり、クラスが初めて使用されるとき、この変数はロードされ、ストレージの一部にすぎません。スペースが割り当てられ、オブジェクトは (このスレッド内で定義されている限り) この変数を操作できます。
1. [必須] switch ブロック内では、各 case をブレーク/リターンなどで終了するか、switch ブロック内でどのケースでプログラムが実行を継続するかを示すコメントを指定する必要があります。 、コードがない場合でも、default ステートメントを含めて最後に配置する必要があります。
2. [必須] if/else/for/while/do ステートメントでは中かっこを使用する必要があります。コードが 1 行しかない場合でも、次の形式の使用は避けてください。それらをできるだけ使用しないことをお勧めします。それ以外の場合、if-else メソッドは次のように書き換えることができます:
if(condition){
...
return obj;
}
// 次に、else ビジネス ロジック コードを記述します。
注: if()... Else if()...else... を使用する必要がある場合は、論理を表現することを意味します。 [必須] 3 レベルを超えないようにしてください。3 レベルを超える場合は、状態設計パターンを使用してください。
良い例: 3 レベルを超えるロジックを持つ if-else コードは、ガード ステートメントまたは状態パターンを使用して実装できます。
4. [推奨] 一般的なメソッド (getXxx/isXxx など) を除き、条件判定では他の複雑なステートメントを実行せず、可読性を高めるために複雑な論理判定の結果を意味のあるブール変数名に割り当てます。
//擬似コードは以下の通り
boolean selected = (file.open(fileName, "w") != null) && (...) (...);
if (存在しました) {
...
}
反例:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
...
}
5 [推奨事項] ループ本体内のステートメントでは、オブジェクト、変数の定義、データベース接続の取得、不要な try-catch 操作の実行など、次の操作をループの外に移動して処理するようにしてください (これは可能ですか)。 try-catch を in vitro でループに移すことはできますか?
6. [推奨] インターフェイス入力パラメーターの保護 このシナリオは、バッチ操作に使用されるインターフェイスに一般的です。
7. 【参考】メソッド内でパラメータの検証が必要なシナリオ:
3) 極めて高い安定性と可用性が要求される方式。
5) 機密性の高いアクセス許可の入り口。
8. 【参考】メソッド内でパラメータの検証が不要なシナリオ:
2. [必須] すべての抽象メソッド (インターフェイス内のメソッドを含む) には、戻り値、パラメーター、例外の説明に加えて、メソッドが何を行うか、どのような関数を実装するかを示す必要があります。
注:サブクラスの実装要件や呼び出し上の注意点について説明してください。
3. 【必須】全てのクラスに作成者情報を追加する必要があります。
4. [必須] メソッド内の単一行のコメント。コメントされたステートメントの上に新しい行を開始し、// コメントを使用します。メソッド内の複数行のコメントには /* */ コメントを使用し、コードと必ず揃えてください。
5. [必須] すべての列挙型フィールドには、各データ項目の目的を説明するコメントが必要です。
6. [推奨] 中途半端な英語でコメントするよりも、中国語のコメントを使用して問題を明確に説明する方が良いです。固有名詞やキーワードは英語の原文のままでも構いません。
カウンターの例: 「TCP 接続タイムアウト」は「伝送制御プロトコル接続タイムアウト」として解釈され、理解するのがさらに面倒です。
7. [推奨] コードを変更するときは、特にパラメーター、戻り値、例外、コア ロジックなどの変更に応じてコメントも変更する必要があります。
注: 道路ネットワークとナビゲーション ソフトウェアの更新が同期していないのと同じように、コードと注釈の更新も同期していません。ナビゲーション ソフトウェアの遅れが深刻な場合、ナビゲーションの意味が失われます。
8. [参考] コメントアウトしたコードは、単にコメントアウトするのではなく、できるだけ記述と一致させる必要があります。
注: コードをコメントアウトするには 2 つの可能性があります:
1) このコードのロジックは後で復元されます。
2)絶対に使用しないでください。前者に発言情報がないと、アノテーションの動機を知ることが困難となる。後者は直接削除することをお勧めします (コード リポジトリには履歴コードが保存されます)。
9. [参考] コメントの要件:
第一に、設計アイデアとコードロジックを正確に反映できること、
第二に、他のプログラマーがコードの背後にある情報をすぐに理解できるように、ビジネス上の意味を説明できること。コメントのない大きなコードの塊は、読者にとっては聖典のようなものであり、コメントは自分が読むためのものであり、時間が経ってもその時の考え方を明確に理解するためのものです。 、彼らがあなたの仕事をすぐに引き継ぐことができるようにします。
10. [参考] 適切な名前付けとコード構造は一目瞭然であり、コメントは簡潔、正確、表現力豊かである必要があります。極端なコメントは避けてください。つまり、コメントが多すぎる、または過剰になるということです。コードのロジックを変更すると、コメントを変更するのはかなりの負担になります。
カウンターの例:
// put elephant into fridge
put(elephant, fridge);
メソッド名 put と 2 つの意味のある変数名 elephant と Bridge は、これが何をしているのかをすでに説明しており、明確なセマンティクスを持つコードは次のとおりです。追加のコメントが必要ではありません。
11. 【参考】特別なコメントマークについては、マークした人、マークした時刻を明記してください。これらのマークをタイムリーに処理するよう注意し、マーク スキャンを通じてこのようなマークを頻繁に清掃してください。オンライン障害は、これらのマークのコードに起因する場合があります。
1)やるべきこと(TODO):(マークする人、マークする時間、【推定処理時間】) 実装する必要があるが、まだ実装されていない機能を示します。これは実際には Javadoc タグです。現在の Javadoc はまだ実装されていませんが、広く使用されています。クラス、インターフェース、およびメソッドにのみ適用できます (Javadoc タグであるため)。 2) エラー、動作できません (FIXME): (マーク名、マーク時間、[推定処理時間]) コメント内で FIXME を使用して、特定のコードが間違っていて動作せず、時間内に修正する必要があることをマークします。
1. 【必須】正規表現を使用する場合は、そのプリコンパイル機能をうまく活用して、正規表現のマッチングを効果的に高速化します。
注: メソッド本体では定義しないでください: Pattern pattern = Pattern.compile(rule);
2. 【必須】Velocity が POJO クラスの属性を呼び出すときは、属性名を直接使用して取得することをお勧めします。 POJO の getXxx() を呼び出すと、それがブール型の基本データ型変数 (ブール名の前に is を付ける必要はありません) の場合、isXxx() メソッドが自動的に呼び出されます。
注: ブール型ラッパークラスオブジェクトの場合、getXxx() メソッドが最初に呼び出されることに注意してください。
3. [必須] バックグラウンドでページに送信される変数は、真ん中に $!{var} (感嘆符) を追加する必要があります。
注: var=null または存在しない場合は、${var} がページに直接表示されます。
4. [必須] Math.random() は double 型を返すことに注意してください。値の範囲は 0 ≤ であり、x を 10 倍に拡大して丸めないでください。Random の nextInt メソッドまたは nextLong メソッドを直接使用してください。物体。
5. 【必須】 new Date().getTime(); の代わりに System.currentTimeMillis(); を使用して現在のミリ秒数を取得します
注: より正確なナノ秒の時間値を取得したい場合は、System.nanoTime を使用してください。 ()。 JDK8 では、統計時間などのシナリオには Instant クラスを使用することをお勧めします。
6. [推奨事項] VM テンプレートに複雑なロジックはもちろん、変数宣言や論理演算子も追加しないようにしてください。
7. [推奨事項] データ構造が無制限に増大してメモリを使い果たさないように、データ構造を構築または初期化するときにサイズを指定する必要があります。
8. [推奨事項] メソッド、変数、クラス、設定ファイル、動的設定属性などの「明らかに使用されていないコードと設定」については、悪影響を避けるために断固としてプログラムから削除する必要があります。ゴミが多い。
1. 【必須】IndexOutOfBoundsException / NullPointerException などの Java クラスライブラリで定義されたランタイム例外クラスをキャッチしません。プログラマを回避し、プログラムの堅牢性を確保するため。
正の例: if(obj != null) {...}
反例: try { obj.method() } catch(NullPointerException e){...}
2. 【必須】例外を使用しない。プロセス制御、条件制御。条件分岐に比べて例外処理効率が低いため。
3. [必須] コードの大部分をトライキャッチしますが、これは無責任です。キャッチする際には、安定したコードと不安定なコードを区別してください。安定したコードとは、何をしても失敗しないコードを指します。不安定なコードをキャッチするには、例外の種類をできる限り区別して、対応する例外を処理するようにしてください。
4. [必須] 例外を処理するために例外をキャッチします。処理したくない場合は、例外を呼び出し元にスローしてください。最も外側のビジネス ユーザーは例外を処理し、例外をユーザーが理解できるコンテンツに変換する必要があります。
5. [必須] 例外をキャッチした後、トランザクションをロールバックする必要がある場合は、トランザクションを手動でロールバックするように注意する必要があります。
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) 戻り値の型が null である可能性があるので注意してください。 null 値に。
カウンターの例: public int f(){ return Integer object}; null の場合は、自動的にアンボックス化され、NPE がスローされます。
2) データベースのクエリ結果がnullになる可能性があります。
3) コレクション内の要素がisNotEmptyであっても、取り出したデータ要素がnullの場合があります。
4) リモート呼び出しで返されるオブジェクトにはNPE判定が必要です。
5) セッションで取得したデータについては、null ポインタを避けるために NPE をチェックすることをお勧めします。
6) obj.getA().getB().getC(); へのカスケード呼び出しは、一連の呼び出しによって簡単に NPE を引き起こす可能性があります。
11. [推奨事項] コード内で「例外のスロー」を使用するか、「エラー コードを返す」を使用するか。社外の http/api オープン インターフェイスの場合は、アプリケーション内で「エラー コード」を使用する必要があります。クロスアプリケーション RPC は、Result メソッドを使用して Prioritize を呼び出し、isSuccess、「エラー コード」、および「エラー概要情報」をカプセル化します。 注: RPC メソッドの戻りに Result メソッドを使用する理由:
1) 例外の戻りメソッドを使用すると、呼び出し元が例外をキャッチしないと実行時エラーが発生します。
2) スタック情報を追加せず、新しいカスタム例外を追加し、エラー メッセージについての独自の理解を追加するだけでは、呼び出し側の問題解決にはあまり役に立ちません。スタック情報を追加した場合、呼び出しエラーが多発した場合、データのシリアル化や送信のパフォーマンス低下も問題となります。
12. [推奨事項] 定義時に未チェック例外とチェック済み例外を区別し、RuntimeException を使用して直接スローすることを避け、ビジネス上の意味を持つ Exception または Throwable を使用する必要があります。 DAOException / ServiceException など、業界で定義されているカスタム例外を推奨します。13. 【参考】コードの重複を避ける(Don'trepeat Yourself)、つまりDRY原則。 注: コードを自由にコピーして貼り付けると、必然的にコードの重複が発生し、将来変更が必要になった場合はすべてのコピーを変更する必要があるため、見落としがちです。必要に応じて、共通メソッド、抽象パブリック クラス、さらには共有モジュールを抽出します。
良い例: クラス内に複数の public メソッドがあり、それらはすべて同じパラメーター検証操作を複数行実行する必要があります。このとき、次を抽出してください:
1. [必須] アプリケーションはログシステムの API (Log4j、Logback) を直接使用することはできませんが、ログフレームワーク SLF4J の API を使用する必要があります。各クラスのログ処理方法が統一されるため、メンテナンスが容易になります。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private staticfinal Logger logger = LoggerFactory.getLogger(Abc.class);
2. 【必須】ログファイルは少なくとも15日間保存することを推奨します。 , 一部の例外では「Week」が周波数特性となっているためです。
3. 【必須】アプリケーションの拡張ログ(管理、一時監視、アクセスログなど)の命名方法:appName_logType_logName.log。 logType: ログの種類。推奨されるカテゴリには、stats/desc/monitor/visit などが含まれます。 logName: ログの説明。この種の名前付けの利点は、ファイル名を通じてログ ファイルがどのアプリケーションに属しているか、どのタイプ、どのような目的であるかを知ることができるため、分類や検索にも役立ちます。
良い例: mppserver アプリケーションでタイム ゾーン変換の例外を個別に監視する (例: mppserver_monitor_timeZoneConvert.log) 注: エラー ログとビジネス ログはできる限り分けて保存することをお勧めします。開発者が閲覧できるほか、ログを通じてシステムをタイムリーに監視するのにも便利です。
4. [必須] トレース/デバッグ/情報レベルのログ出力には、条件付き出力フォームを使用するか、プレースホルダーを使用する必要があります。
説明: logger.debug("Processing trade with id: " + id + "symbol: " +symbol); ログレベルがwarnの場合、上記のログは出力されませんが、文字列の結合操作が実行されます。シンボルが object の場合、 toString() メソッドが実行され、上記の操作を実行した後、最終的なログは出力されません。
正の例: (条件)
if (logger.isDebugEnabled()) {
logger.debug("ID で取引を処理中: " + id + " シンボル: " + シンボル);
}
正の例: (プレースホルダーシンボル) )
logger.debug("Processing trade with id: {}Symbol : {} ", id,symbol);
5. 【必須】ログを繰り返し出力してディスク容量を無駄にしないように、log4j で additivity= を必ず設定してください。 XML は false です。
肯定的な例:
6. [必須] 例外情報には、犯罪現場情報と例外スタック情報の 2 種類の情報が含まれている必要があります。そうでない場合は、吐きます。
正の例: logger.error(variousparameters or object toString + "_" + e.getMessage(), e);
7. [推奨事項] 警告ログ レベルを使用して、ユーザー入力パラメーターのエラーを記録できます。ユーザーは苦情を言い、途方に暮れています。ログ出力のレベルに注意してください。エラー レベルには、システム ロジック エラーや例外などの重要なエラー情報のみが記録されます。必要がない場合は、このシナリオではエラー レベルを入力しないでください。
8. [推奨] ログを注意深く記録します。本番環境でデバッグ ログを出力することは禁止されています。最初の起動時に warn を使用してビジネス動作情報を記録する場合は、サーバー ディスクのバーストを避けるためにログ出力の量に注意する必要があります。これらの観察ログは時間内に忘れずに削除してください。
注: 無効なログを大量に出力することは、システムのパフォーマンスの向上やエラーポイントの迅速な特定にはつながりません。ログを記録するときは、次のことを考えてください: 本当にこれらのログを読んでいる人はいるのでしょうか?このログを見た後、何ができるでしょうか?トラブルシューティングにメリットをもたらすでしょうか?
1. [必須] はいまたはいいえの概念を表すフィールドは、is_xxx を使用して名前を付ける必要があり、データ型は unsigned tinyint (1 は Yes を意味し、0 は Yes を意味します) no) の場合、このルールは odps テーブルの作成にも適用されます。
注: フィールドが負ではない数値の場合、符号なしでなければなりません。
2. [必須] テーブル名とフィールド名には小文字または数字を使用する必要があり、先頭に数字を使用することは禁止されており、2 つのアンダースコア間の数字のみが禁止されています。データベースのフィールド名の変更は、プレリリースが不可能なため非常にコストがかかり、そのためフィールド名を慎重に検討する必要があります。
正の例:getter_admin、task_config、level3_name
反例:GetterAdmin、taskConfig、level_3_name
3. 【必須】テーブル名には複数の名詞を使用しないでください。 注: テーブル名はテーブル内のエンティティの内容のみを表す必要があり、対応する DO クラス名も表現の習慣に従って単数形にする必要があります。
4. [必須] desc、range、match、delayed などの予約語を無効にします。MySQL 公式の予約語を参照してください。
5. [必須] 一意のインデックス名は uk_field 名、共通インデックス名は idx_field 名です。 注: uk_ は一意のキー、idx_ はインデックスの省略形です。
6. 【必須】10進数型は10進数、float、doubleは禁止です。
注: float と double を格納するときに精度が失われるという問題があり、値を比較するときに誤った結果が得られる可能性があります。保存されるデータの範囲が小数の範囲を超える場合は、データを整数と小数に分割して別々に保存することをお勧めします。
7. 【必須】格納する文字列の長さがほぼ等しい場合は、char固定長文字列型を使用してください。
8. [必須] Varchar は可変長文字列です。長さは 5000 を超えてはなりません。格納長がこの値を超える場合は、フィールド タイプをテキストとして定義し、別のテーブルを作成します。 、他のフィールドのインデックス効率への影響を避けるために対応する主キーを使用します。
9. [必須] テーブルには id、gmt_create、gmt_modified の 3 つのフィールドが必要です。
注: ID は主キーである必要があり、型は unsigned bigint、単一テーブルの自動インクリメント、ステップ サイズは 1 です。 gmt_create および gmt_modified の型はすべて date_time 型です。
10. [推奨] テーブル名は「業務名_テーブルの機能」とするのがベストです。 肯定的な例: Tiger_task / Tiger_reader / mpp_config
11. [推奨事項] ライブラリ名とアプリケーション名は可能な限り一致する必要があります。
12. [推奨事項] フィールドの意味を変更したり、フィールドが表すステータスを追加したりする場合は、フィールドのコメントを適時に更新する必要があります。
13. [推奨] パフォーマンスを向上させるためにフィールドに適切な冗長性を許可しますが、データの同期を考慮する必要があります。冗長なフィールドは次のとおりです:
1) 頻繁に変更されないフィールド。 2) varchar の超長いフィールドではなく、ましてやテキスト フィールドでもありません。
良い例: 製品カテゴリ名が頻繁に使用され、フィールドの長さが短く、名前は基本的に変更されないため、関連するクエリを回避するために、カテゴリ名を関連テーブルに重複して格納できます。
14. [推奨事項] データベースとテーブルのシャーディングは、単一テーブルの行数が 500 万を超える場合、または単一テーブルの容量が 2GB を超える場合にのみ推奨されます。
注: データ量が 3 年以内にこのレベルに達しないことが予想される場合は、テーブルを作成するときにデータベースをテーブルに分割しないでください。
15. [参考] 適切な文字ストレージ長は、データベースのテーブルスペースとインデックスストレージを節約するだけでなく、さらに重要なことに、検索速度も向上します。
正の例: 人の年齢には unsigned tinyint を使用します (0 ~ 255 の範囲を示し、人の寿命は 255 歳を超えません)。カメは smallint でなければなりませんが、それが太陽の年齢の場合、オールスターの場合は int でなければなりません。年齢が合計される場合は、bigint を使用する必要があります。
1. 【必須】業務上固有の特性を持つフィールドは、複合フィールドであっても固有のインデックスを構築する必要があります。
注: ユニークなインデックスが挿入速度に影響を与えるとは考えないでください。この速度低下は無視できますが、アプリケーション層で非常に完全なチェックサム制御が行われた場合でも、検索速度の向上は明らかです。 Mo氏によると、一意のインデックスがない限り、フィーの法則に従って、ダーティデータを生成する必要があります。
2. 【必須】3テーブル以上の参加は禁止です。結合する必要があるフィールドのデータ型は完全に一貫している必要があります。複数のテーブルをクエリする場合は、関連するフィールドにインデックスが必要であることを確認してください。
注: 二重テーブルを結合する場合でも、テーブルのインデックスと SQL のパフォーマンスに注意を払う必要があります。
3. [必須] varchar フィールドにインデックスを作成する場合は、インデックスの長さを指定する必要があります。インデックスの長さは、実際のテキストの区別に基づいて決定されます。
注: インデックスの長さと区別は矛盾しています。一般に、文字列型データの場合、長さが 20 のインデックスの区別は 90% 以上になります。 count(distinct を使用できます)。 left(列名、インデックス長) )/count(*)。
4. [必須] ページ検索での左ぼかしまたは全体ぼかしの使用は固く禁止されています。必要に応じて、問題を解決するために検索エンジンを使用してください。
注:インデックスファイルにはB-Treeの左端のプレフィックスマッチング機能があり、左端の値が不定の場合、このインデックスは使用できません。
5. [推奨事項] シナリオごとの順序がある場合は、インデックスの順序に注意してください。 order by の最後のフィールドは結合インデックスの一部であり、file_sort を回避してクエリのパフォーマンスに影響を与えるために、インデックス結合順序の最後に配置されます。
正の例: where a=? and b=? order by c; インデックス: a_b_c
逆の例: インデックス内に範囲検索があるため、インデックスの順序は使用できません。例: WHERE a>10 BY b; インデックス a_b ソートできません。
6. [推奨] テーブルの戻り操作を回避するために、クエリ操作を実行するにはカバリング インデックスを使用します。
説明: 本で第 11 章のタイトルを知る必要がある場合、第 11 章に対応するページが開きますか?ディレクトリを参照するだけです。このディレクトリはカバーインデックスとして機能します。
良い例: 作成できるインデックスの種類: 主キー インデックス、一意のインデックス、通常のインデックス、カバリング インデックスは、クエリの効果により、追加の列が表示されます: インデックスを使用します。
7. [推奨] 遅延相関またはサブクエリを使用して、複数ページのページング シナリオを最適化します。
説明: MySQL はオフセット行をスキップせず、オフセット + N 行を取得し、諦める前にオフセット行を返し、オフセットが特に大きい場合、効率が非常に低い、または合計が N 行を返します。戻り値のページ数を制御するか、特定のしきい値を超えたページ数で SQL リライトを実行します。
肯定的な例: まず、取得する必要がある ID セグメントをすばやく見つけてから、関連付けます: SELECT a.* FROM table 1 a, (select id from table 1 where 条件 LIMIT 100000,20) b where a.id=b. id
8 . [推奨事項] SQL パフォーマンス最適化の目標: 少なくとも range レベルに達すること、要件は ref レベル、const にできる場合はそれが最適です。
手順:
1) 定数 1 つのテーブル内に一致する行 (主キーまたは一意のインデックス) が最大 1 つあり、最適化フェーズ中にデータを読み取ることができます。
2) ref は、通常のインデックスを使用することを指します。
3) range はインデックスに対して範囲検索を実行します。
カウンターの例: Explain テーブル type=index の結果は、インデックス物理ファイルのフル スキャンですが、このインデックス レベルは範囲よりも低く、フル テーブル スキャンよりも劣ります。
9. [推奨事項] 結合インデックスを作成する場合、最も区別されるものは左端にあります。 良い例: a=? および b=? の場合、列 a がほぼ一意の値に近い場合、単一の idx_a インデックスを作成するだけで済みます。
注:不等号と等号の判定条件が混在する場合、インデックスを構築する際に等号条件の列を前に置いてください。例: where a>? and b=? この場合、a の方が区別性が高い場合でも、b をインデックスの先頭に配置する必要があります。
10. 【参考】インデックスを作成する際は、次のような極端な誤解を避けてください:
1) クエリにはインデックスが必要であるという誤解。
2) インデックス作成によりスペースが消費され、更新や新規追加が大幅に遅くなるという誤解。
3) 一意のインデックスは常に「最初にチェックしてから挿入」方法を通じてアプリケーション層で解決する必要があると誤って信じられています。
1. [必須] count(*)の代わりにcount(列名)またはcount(定数)を使用しないでください。 count(*)はSQL92で定義されている行をカウントするための標準構文です。データベースと同じです。NULL か非 NULL かは関係ありません。
注: count(*) は NULL 値を持つ行をカウントしますが、count(列名) はこの列内の NULL 値を持つ行をカウントしません。
2. [必須] count(distinctcol) NULL を除く列内の個別の数値の数を計算します。いずれかの列がすべて NULL の場合、他の列の値が異なる場合でも、 count(distinctcol1,col2) は 0 を返すことに注意してください。
3. 【必須】あるカラムの値が全てNULLの場合、count(col)の戻り結果は0ですが、sum(col)の戻り結果はNULLとなるので注意が必要です。 sum() 使用時の NPE の問題。
良い例: 合計の 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. [必須] コード内でページング クエリ ロジックを記述する場合、カウントが 0 の場合は、後続のページング ステートメントの実行を避けるために、それを直接返す必要があります。
6. [必須] 外部キーとカスケードは許可されません。すべての外部キーの概念はアプリケーション層で解決される必要があります。 注: (概念の説明) Student テーブルの Student_id が主キーであり、Grades テーブルの Student_id が外部キーです。 Student テーブルの Student_id が更新され、成績テーブルの Student_id が同時に更新される場合、それはカスケード更新です。外部キーとカスケード更新は、単一マシンでの同時実行性が低い場合には適していますが、分散型の同時実行性が高いクラスターには適していません。カスケード更新は強力にブロックされ、データベース更新の嵐がデータベースの挿入速度に影響を与えるリスクがあります。 。
7. 【必須】ストアドプロシージャの使用は禁止されており、デバッグや拡張が難しく、移植性がありません。
8. [必須] データを修正するとき、レコードを削除または変更するときは、誤って削除しないように最初に選択する必要があり、確認後にのみ更新ステートメントを実行できます。
9. [推奨] in 操作が回避できる場合は回避し、in の背後にあるコレクション要素の数を慎重に評価し、1,000 以内に制御する必要があります。
10. [参考] グローバリゼーションが必要な場合は、すべての文字の保存と表現が utf-8 でエンコードされているため、文字のカウント方法に注意してください:
説明: SELECT LENGTH ("Easy Work"); CHARACTER_LENGTH ("簡単な作業"); 4 に戻ります。絵文字を使用する場合は、utf-8 エンコードとの違いに注意してください。
11. [参考] TRUNCATE TABLE は DELETE よりも高速で、システムおよびトランザクション ログのリソースの使用量が少なくなります。ただし、TRUNCATE にはトランザクションがなく、トリガーが発生しないため、開発中にこのステートメントを使用することはお勧めできません。コード。
注: TRUNCATE TABLE は、WHERE 句のない DELETE ステートメントと機能的には同じです。
1. [必須] テーブルクエリでは、クエリのフィールドリストとして*を使用しないでください。どのフィールドが必須であるかを明確に記述する必要があります。
手順:
1) クエリ アナライザーの解析コストを増やします。
2) フィールドの追加や削除は、resultMap の設定と矛盾しやすくなります。
2. [必須] POJO クラスのブール属性は is で追加できませんが、データベース フィールドは is_ で追加する必要があり、resultMap 内のフィールドと属性間のマッピングが必要です。
注:POJOクラスの定義とデータベースフィールドの定義を参照 sql.xmlにマッピングを追加する必要があります。
3. [必須] resultClass を戻りパラメータとして使用しないでください。逆に、すべてのクラス属性名がデータベース フィールドに対応するものを定義する必要があります。
説明: メンテナンスを容易にするために、フィールドを DO クラスから分離するようにマッピング関係を構成します。
4. [必須] XML 設定でのパラメーターの使用に注意してください: #{}、#param# このメソッドは SQL インジェクションを発生しやすいです。
5. 【必須】iBATIS付属のqueryForList(String statementName, int start, int size)は推奨しません。
説明: 実装方法は、データベース内のstatementNameに対応するSQL文のレコードをすべて取得し、subListを通じてstartとsizeのサブセットを取得するというもので、この理由によりOOMがオンラインで発生しました。
良い例: sqlmap に #start#, #size#
を導入します。 .put("size", size);
6. [必須] クエリ結果セットの出力として HashMap と Hashtable を直接使用することはできません。 。
7. [必須] データテーブルのレコードを更新するときは、レコードの対応する gmt_modified フィールドの値も現在時刻に更新する必要があります。
8. [推奨事項] 独自の更新フィールドであるかどうかに関係なく、大規模で包括的なデータ更新インターフェイスを作成しないでください。c1=value1,c2=value2,c3=value3 を更新します。 ; これは違います。 SQL を実行するときは、未変更のフィールドを更新しないようにしてください。第一に、エラーが発生しやすくなります。第二に、binlog によりストレージが増加します。
9. 【参考】@Transactionalトランザクションを乱用しないでください。さらに、トランザクションが使用される場合は、キャッシュ ロールバック、検索エンジンのロールバック、メッセージ補正、統計補正など、ロールバック ソリューションのさまざまな側面を考慮する必要があります。
10.
IV. エンジニアリング仕様
端末表示レイヤー: 各端末のテンプレートが表示レイヤーをレンダリングして実行します。現在、主なものは、ベロシティ レンダリング、JS レンダリング、JSP レンダリング、モバイル ディスプレイ レイヤーなどです。
Web 層: 主にアクセス制御の転送、さまざまな基本パラメータの検証、または非再利用サービスの単純な処理など。
サービス層: 比較的特殊なビジネス ロジック サービス層。
マネージャー層: 以下の特徴を持つ一般的なビジネス処理層:
1) サードパーティのプラットフォームをカプセル化し、戻り結果の前処理と例外情報の変換を行う層
2) サービス層の一般的な機能をシンクする。キャッシュソリューションとして、ミドルウェアの一般的な処理
3) DAO レイヤーと対話して、DAO の一般的なビジネス機能をカプセル化します。
DAO レイヤー: データ アクセス レイヤー。基盤となる MySQL、Oracle、および Hbase とデータをやり取りします。 外部インターフェイスまたはサードパーティ プラットフォーム: 他の部門の RPC オープン インターフェイス、基本プラットフォーム、他社の HTTP インターフェイスが含まれます。
2. 【参考】(階層型例外処理プロトコル) DAO層では多くの種類の例外が発生しますが、catch(Exception e)メソッドを使用してnew DAOException(e)をスローすることはできません。ログをマネージャー/サービス層でキャプチャしてログ ファイルに書き込む必要があるため、ログを印刷する必要はありません。同じサーバーがログを再度印刷すると、パフォーマンスとストレージが無駄になります。サービス層で例外が発生した場合、ログ情報をディスクに記録し、パラメータ情報を可能な限り含める必要があり、これは犯罪現場を保護することに相当します。マネージャー層とサービスが同じマシンにデプロイされている場合、ロギング方法は DAO 層の処理と一致します。別々にデプロイされている場合、ロギング方法はサービスと一致します。 Web レイヤーは例外をスローし続けることはできません。Web レイヤーはすでに最上位にあるため、例外の処理を続行する方法がなく、この例外によってページが正常に表示されなくなることがわかった場合は、次のページに直接ジャンプする必要があります。フレンドリーなエラー ページを表示し、フレンドリーなエラー メッセージを追加してみます。オープン インターフェイス層は例外を処理し、エラー コードとエラー メッセージの形式で例外を返す必要があります。
3. [参考] 階層ドメインモデル仕様:
DO (Data Object): データベースのテーブル構造と 1 対 1 に対応し、DAO 層を介してデータ ソース オブジェクトを上方向に送信します。
DTO (Data Transfer Object): データ転送オブジェクト。Service および Manager によって外部に転送されるオブジェクト。
BO (ビジネスオブジェクト): ビジネスオブジェクト。ビジネス ロジックをカプセル化し、サービス層によって出力できるオブジェクト。
クエリ: データ クエリ オブジェクト。各層は上位層からクエリ リクエストを受け取ります。注: 3 つ以上のパラメーターを含むクエリのカプセル化では、送信に Map クラスを使用することは禁止されています。
VO (View Object): 表示レイヤー オブジェクト。通常は Web によってテンプレート レンダリング エンジン レイヤーに送信されるオブジェクトです。
(2) ツーパーティライブラリ仕様
1) GroupID 形式: com.{会社/BU}.Business Line.[Sub-Business Line]、最大 4 レベル。
説明: {会社/BU} 例: alibaba/taobao/tmall/aliexpress およびその他のサブビジネス ラインはオプションです。
肯定的な例: com.taabao.jstorm または com.alibaba.dubbo.register
2) ArtifactID 形式: 製品ライン名-モジュール名。セマンティクスが繰り返されたり省略されたりすることはありません。まず、倉庫センターに行って確認してください。
肯定的な例: dubbo-client / fastjson-api / jstorm-tool 3) バージョン: 以下の詳細を参照してください。
2. [必須] セカンドパーティライブラリのバージョン番号の命名方法: メジャーバージョン番号。マイナーバージョン番号。
1) メジャーバージョン番号: 互換性のない API の変更が行われた場合、または製品の方向性を変更する可能性のある新機能。が追加されます。
2)マイナーバージョン番号:下位互換性のある機能追加(新しいクラス、インターフェースなど)として扱われます。
3) リビジョン番号: バグを修正し、メソッドのシグネチャを変更せずに機能を強化し、API の互換性を維持しました。
注: 開始バージョン番号は 0.0.1 ではなく 1.0.0 である必要があります
3。 [必須] オンライン アプリケーションは SNAPSHOT バージョンに依存しません (セキュリティ パッケージを除く)。 RELEASE バージョン番号 +1 メソッドでは、バージョン番号の上書きとアップグレードが許可されていないため、中央倉庫に行って確認する必要があります。
注: SNAPSHOT バージョンに依存しないことで、アプリケーションリリースの冪等性が保証されます。さらに、コンパイル時のパッケージ化と構築も高速化できます。
4. [必須] セカンドパーティライブラリの追加またはアップグレードにより、関数ポイントを除く他の jar パッケージの調停結果は変更されません。変更がある場合は、それらを明確に評価および検証する必要があります。 dependency:resolve の前後で情報を比較することをお勧めします。調停結果が完全に矛盾している場合は、dependency:tree コマンドを使用して相違点を見つけ、
6. [必須] サードパーティのライブラリ グループに依存する場合、バージョン番号の不一致を避けるために統合バージョン変数を定義する必要があります。
説明: springframework-core、-context、-beans に依存します。これらはすべて同じバージョンです: ${spring.version} という変数を定義できます。依存関係を定義するときは、このバージョンを参照します。
7. [必須] サブプロジェクトの pom 依存関係で、同じ GroupId、同じ ArtifactId、ただし異なるバージョンを持つことは禁止されています。
注: ローカルでデバッグする場合、各サブプロジェクトで指定されたバージョン番号が使用されますが、war にマージされる場合、最終的な lib ディレクトリに表示できるバージョン番号は 1 つだけです。オフラインでのデバッグは正しくても、オンラインでリリースすると問題が発生したという前例があります。
8. [推奨] すべての pom ファイルの依存関係宣言を
注:
9. [推奨事項] セカンドパーティのライブラリは構成項目を持たないようにする必要があり、少なくともこれ以上構成項目を追加しないでください。
10. [参考] セカンドパーティライブラリを適用する際に依存関係の競合を避けるために、セカンドパーティライブラリの発行者は次の原則に従う必要があります:
1) 単純さと制御性の原則。サービス API、必要なドメイン モデル オブジェクト、Utils クラス、定数、列挙などのみを含む、不要な API と依存関係をすべて削除します。他のセカンドパーティ ライブラリに依存する場合は、provided を通じてそれらを導入するようにしてください。これにより、サードパーティ ライブラリのユーザーが特定のバージョン番号に依存できるようになります。ログの特定の実装はなく、ログ フレームワークのみに依存します。
2)安定したトレーサビリティ原則。各バージョンの変更を記録する必要があり、誰がセカンド パーティ ライブラリを保守しているか、ソース コードがどこにあるか、すべてに簡単にアクセスできる必要があります。ユーザーが積極的にバージョンをアップグレードしない限り、パブリックのセカンドパーティ ライブラリの動作は変更されるべきではありません。
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 です。同時接続の数が多い場合、FD の不足により「ファイルが多すぎます」エラーが発生しやすくなり、新しい接続の確立に失敗します。 Linux サーバーでサポートされるハンドルの最大数を数倍に増やすことをお勧めします (サーバーのメモリ量に関連します)。
3. [推奨] -XX:+HeapDumpOnOutOfMemoryError パラメーターを JVM に設定して、OOM シナリオが発生したときに JVM がダンプ情報を出力できるようにします。
注: OOM は確率的に発生し、さらには数か月ごとに定期的に発生します。発生したときのオンサイト情報は、トラブルシューティングに非常に役立ちます。
4. [参考] サーバーの内部リダイレクトには forward を使用します。外部リダイレクト アドレスを生成するには URL アセンブリ ツール クラスを使用します。そうしないと、一貫性のない URL メンテナンスが発生し、潜在的なセキュリティ リスクが発生します。
1. [必須] ユーザーに属するページまたは機能は権限制御の検証を受ける必要があります。 注: これにより、ユーザーは、他の人の注文の表示や変更など、水平的な権限の検証を実行せずに、他の人のデータに自由にアクセスして操作できなくなります。
2. [必須] 機密性の高いユーザーデータの直接表示は禁止されており、表示データは機密性を解除する必要があります。 注: 個人の携帯電話番号を表示すると、プライバシー漏洩を防ぐために中央の 4 桁が隠されて、「158****9119」と表示されます。
3. [必須] SQL インジェクションを防止し、文字列スプライシング SQL によるデータベースへのアクセスを禁止するために、ユーザーが入力する SQL パラメーターはパラメーター バインディングまたは METADATA フィールド値によって厳密に制限する必要があります。
4. [必須] ユーザーが渡したパラメータは有効であるかどうかを検証する必要があります。 注: パラメーターの検証を無視すると、次のような問題が発生する可能性があります。
メモリ オーバーフローを引き起こす過剰なページ サイズ
遅いデータベース クエリの原因による悪意のある順序
任意のリダイレクト
SQL インジェクション
逆シリアル化インジェクション
通常の入力ソース文字列のサービス拒否 ReDoS の説明: Java JavaJava コードでは、正規表現を使用してクライアントの入力を検証します。一部の正規表現では、通常のユーザー入力を問題なく検証できますが、攻撃者が検証に特別に作成した文字列を使用すると、無限ループが発生する可能性があります。
5. 【必須】安全にフィルタリングされていない、または正しくエスケープされていないユーザーデータをHTMLページに出力することは禁止されています。
6. [必須] フォームと AJAX の送信に対して CSRF セキュリティ フィルタリングを実行する必要があります。 説明: CSRF (クロスサイト リクエスト フォージェリ) は、一般的なプログラミングの脆弱性です。 CSRF 脆弱性のあるアプリケーション/Web サイトの場合、攻撃者は被害ユーザーがアクセスするとすぐに、ユーザーの知らないうちにバックグラウンドでデータベース内のユーザー パラメーターを変更する可能性があります。
7. [必須] テキスト メッセージ、電子メール、電話、注文、支払いなどのプラットフォーム リソースを使用する場合、数量制限、疲労制御、確認コードの検証などの正しいリプレイ防止制限を実装する必要があります。虐待と虐待。
注:登録中に確認コードが携帯電話に送信される場合、数と頻度に制限がない場合、この機能は他のユーザーに嫌がらせをするために使用され、SMSプラットフォームのリソースの浪費を引き起こす可能性があります。
以上がJavaコーディング仕様を分析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。