春には多くの場合にコミットしたことがない(コレクション後)、10個のエラーを犯し

1.間違い:根本的にあまりにも多くの注意

「ここに発明されていない」症候群は、ソフトウェア開発では非常に一般的ですので、私たちは、この一般的な間違いに取り組んでいます。いくつかの一般的な症状が頻繁に書き換えたコードが含まれ、多くの開発者は、この症状を持っています。

特定のライブラリとその実装の内部構造を理解しながら、大幅に優れかつ必要である(それは良い学習プロセスすることができます)が、ソフトウェア・エンジニアとして、同じ基本となる実装の詳細に対処していき個人のキャリア開発は有害です。

この抽象化Springフレームワークが理由でありそこにあるように、それは手作業で繰り返しからあなたを解放し、あなたがより高いレベルの内容に集中することができます - ドメインオブジェクトとビジネス・ロジック。

したがって、抽象を受け入れます。あなたが特定の問題に直面して、次回、最初のクイック検索は、この問題を解決するためのライブラリが春に統合されているかどうかを決定するために、今、あなたは、適切な既製のソリューションを見つけるかもしれません。

例えば、有用なライブラリーは、この記事の残りの部分では、私が例では、プロジェクトロンボクアノテーションを使用します。ロンボク島は、モデルのコードジェネレータとして使用されている、怠惰な開発者は、このライブラリに慣れの問題を持っている必要はありません。例えば、ロンボクの使用を見て、「標準のJava Beanが」それは次のようになります。

あなたが想像できるように、以下のように、上記のコードはコンパイルされます。

しかし、あなたはロンボク島でのIDEを使用する場合、それはここでのIntelliJ IDEAプラグイン見つけることができるプラグインのバージョンをインストールする必要がありますのでご注意ください。

2.エラー2:内部構造は「漏れました」

それは、このように貧弱なコーディング手法に貢献し、サービス設計には柔軟性が発生することはありませんので、あなたの内部構造を開き、それは、良いアイデアになることはありません。内部機構は、APIエンドポイントのデータベース構造の一部の性能からアクセス可能な「漏れ」。例えば、以下のPOJO(「プレーンオールドJavaオブジェクト」)クラスは、データベース内のテーブルを表します。

@Entity 
@NoArgsConstructor
@Getter
パブリッククラスTopTalentEntity {
@Id
@GeneratedValue
プライベート整数ID。
@Column
プライベート文字列名;
公共TopTalentEntity(文字列名){
this.name =名。
}
}

エンドポイントがあると仮定し、彼はアクセスTopTalentEntityデータを必要とします。戻りTopTalentEntityインスタンスは魅力的かもしれないが、より柔軟な解決策は、APIエンドポイント上TopTalentEntityデータを表現するために、新しいクラスを作成することです。

@AllArgsConstructor 
@NoArgsConstructor
@Getter
パブリッククラスTopTalentData {
プライベート文字列名;
}

このように、データベースバックエンドへの変更は、サービス層内の任意の追加の変更を加える必要はありません。検討中の、TopTalentEntityでデータベースユーザーパスワードのハッシュ値を格納するための「パスワード」フィールドを追加 - していない場合は、好きなフロントエンドサービスを変更することを忘れ、誤って不要な機密情報にさらされるTopTalentData。

3.エラー3:関心事の分離の欠如

プログラムのサイズの増加に伴い、徐々に、コードの組織はますます重要な課題となっています。特にアプリケーションのアーキテクチャ設計の状況をあまり考慮せず - 皮肉なことに、優れたソフトウェアエンジニアリングの原則のほとんどは規模に崩壊し始めました。間違いは、開発者が最も一般的にコミットし、コードの問題を混同することで、それを行うのは非常に簡単です!

一般的には、懸念の分離は、単に既存のクラスに「反転」の新機能を壊しています。もちろん、これは(先発のため、それが少ない入力を必要とする)良い短期的な解決策であるが、それは必然的にそれがテスト中であるかどうか、将来的に問題となって、メンテナンス、またはどこかの間になります2間。それは、データベースからTopTalentDataを返し、次のコントローラを考えてみましょう。

@RestController 
パブリッククラスTopTalentController {
民間最終TopTalentRepository topTalentRepository。
@RequestMapping( "/ toptal /取得")
公共の一覧<TopTalentData> getTopTalent(){
返すtopTalentRepository.findAll()
.stream()
.MAP(本:: entityToData)
.collect(Collectors.toList());
}
プライベートTopTalentData entityToData(TopTalentEntity topTalentEntity){
戻り新しいTopTalentData(topTalentEntity.getName())。
}
}

最初に、コードは特段の問題はないように思われる。それはTopTalentEntityインスタンスTopTalentDataの一覧から取得しています。

しかし、注意深い観察の下で、我々はこのTopTalentControllerが実際に何かをしていることがわかります。つまり、それはデータベースからデータを取得、特定のエンドポイントにリクエストをマッピングし、別のTopTalentRepository 1つのフォーマットから受け取ったエンティティを変換し、 。「クリーナー」ソリューションは、自分のクラスにこれらの懸念を分離することです。それは次のようになります。

@RestController 
@RequestMapping( "/ toptal")
@AllArgsConstructor
パブリッククラスTopTalentController {
民間最終TopTalentService topTalentService。
@RequestMapping( "/取得")
公共の一覧<TopTalentData> getTopTalent(){
(topTalentService.getTopTalentを返します)。
}
}
@AllArgsConstructor
@Service
パブリッククラスTopTalentService {
民間最終TopTalentRepository topTalentRepository。
民間最終TopTalentEntityConverter topTalentEntityConverter。
公共の一覧<TopTalentData> getTopTalent(){
返すtopTalentRepository.findAll()
.stream()
.MAP(topTalentEntityConverter :: toResponse)
.collect(Collectors.toList());
}
}
@Component
パブリッククラスToptalentエンティティコンバータ{
公共ToptalentデータtoResponse(Toptalentエンティティタレントエンティティ){
戻り新しいToptalentデータ(topTalentEntity.getName())。
}
}

そのような階層の他の利点は、関数がクラス名をチェックして、存在する場所を決定することができることです。また、必要に応じてテスト中に、我々は簡単に任意のクラスを置き換えるためにアナログを実装することができます。

4.エラー4:不足の例外処理や誤操作

一貫性はユニークですが、それでも春のプロジェクトを扱う際に考慮すべき重要な側面である春(またはJava)のテーマではありません。スタイルが物議を醸すかもしれ(通常は全体の社内チームまたは合意している)が、一般的な標準でコーディングしながら、最終的には大幅に生産性を向上します。これは、複数のチームでは特に顕著であり、一貫性が交換が手に多くのリソースを過ごすには、転送が責任の同じ種類の長い説明を提供していません必要はありませんなくても場所を取ることができます。

春のプロジェクトは、さまざまなコンフィギュレーションファイル、サービス、およびコントローラが含まれて考えてみましょう。命名の意味での一貫性を維持するためには、独自の方法でコードを管理するために、検索簡単に任意の新しい開発者が構造を作成することができ、例えば、コンフィギュレーションConfigクラス、サービスの終了までサービス層だけでなく、制御にサフィックスを追加します使用されるコントローラを終了します。

密接に一貫性のテーマに関連した、サーバー側のエラー処理は、特別な強調に値します。あなたはAPI異常応答の準備不足に対処するために持っていた場合は、おそらくその理由を知っている - 正確に痛みを伴うことになり、異常を解決しますが、これらの異常の原因を決定するために、第1、さらに痛みが発生しました。

API開発者として、理想的には、すべてのユーザー向けエンドを上書きし、一般的なエラー・フォーマットに変換します。これは通常、むしろ問題を解決するためにエスケープよりも、一般的なエラーコードと説明があることを意味します。a)「500内部サーバーエラー」メッセージを返します。ユーザーへのb)に直接リターンスタック例外情報。(取り扱いが難しいクライアントに加えて、それはまたあなたの内部情報を公開しているので実際には、これらは、行くためにすべてのコストで避けるべきです)。

例えば、一般的なエラー応答フォーマットは、長い道のりであってもよいです。

@value 
パブリッククラスはErrorResponse {
プライベート整数のerrorCode。
プライベート文字列にErrorMessage。
}

このようなものは、多くの場合、あなたが簡単かつ体系的に記録することができるので、結果は、多くの場合、非常に優れている、最も人気のあるAPIに遭遇しました。このフォーマットへの例外は、メソッドに@ExceptionHandler注釈を提供することにより、(VI章に見られる場合のメモ)を行うことができます。

5.エラー5:マルチスレッド誤操作

デスクトップやWebアプリケーション、いずれかの春またはNo春かどうかは、マルチスレッドを破るのは難しいです。デバッグに不気味ととらえどころのない、としばしば困難なことに起因するプログラムの並列実行によって引き起こされる問題 - 実際には、問題の性質のために、あなたはあなたが問題の並列実装を扱っていることを認識したら、あなたは完全にあきらめする必要がありますあなたは上のエラーの根本的な原因を見つけるまで、デバッガ、および「マニュアル」は、コードを確認してください。

残念ながら、これらの問題は、クッキーカッターをソリューションではありません。状況を評価し、その後、あなたは最高の角度だと思う問題を解決するために、シーンに応じました。

もちろん、理想的に、あなたは完全にマルチスレッド化エラーを回避したいです。同様に、1つのサイズの種類は、すべてのアプローチが存在していないが、いくつかのマルチスレッドのデバッグがあると誤った実用的な考慮事項を防ぐフィット:

5.1。グローバルな状態を避けます

まず第一に、心の中で「グローバルな状態」の問題を保ちます。あなたは、マルチスレッドアプリケーションを作成する場合は、可能な場合、あなたは、世界的に変更することができるものに細心の注意を払う必要があり、それらはすべて削除されます。グローバル変数を変更することができた理由のために維持されなければならない場合は、新たなシステムの導入を待って、パフォーマンスが低下する時間がないので、慎重に判断するために、同期、およびパフォーマンスの追跡プログラムを使用してください。

5.2。の変動を避けます

これを直接プログラミングから機能、およびOOPの適用は、クラス宣言は回避し、状態を変更する必要があります。要するに、これは、setterメソッドをあきらめ意味し、すべてのモデルクラスの民間最終フィールドがあります。工事中に発生した時間だけその値が変化します。このように、あなたは常に正しい値を提供するプロパティをobjectに競合の問題、およびアクセスできなくなりますことを確認することができます。

5.3。鍵データを記録します

評価プログラムの例外が発生する可能性がありますどこのすべての重要なデータと事前に記録します。エラーが発生した場合、その情報は、要求が受信され、より良い理由を、アプリケーション・エラーを理解するために何を説明することは喜んでいるだろう得ることができます。再度、追加のログ・ファイルの導入は、I / Oを、真剣のでログを乱用しないでください、アプリケーションのパフォーマンスに影響を与えることに注意する必要があります。

5.4。既存の実現を再利用

既存のセキュリティ実装を使用するのではなく、独自のソリューションを再作成するために、:あなたは、(異なるサービスの非同期要求に対して発行など)、独自のスレッドを作成する必要があるとき。これは、主にスレッドを作成しExecutorServicesとJava 8の単純な機能CompletableFuturesを使用することを意味しています。春はまたDeferredResultクラスで非同期リクエスト処理を可能にします。

6.エラー6:アノテーションベースの認証を使用していません

私たちは新しいTopTalentを追加するTopTalentの終了前にサービスを必要とします。また、何らかの理由で仮定に基づいて、すべての新しい用語は、長さが10文字を必要とします。次のようにこれを行うための方法は次のようになります。

( "/ PUT")@RequestMapping 
公共ボイドaddTopTalent(@RequestBody TopTalentData topTalentData){
boolean型nameNonExistentOrHasInvalidLength =
Optional.ofNullable(topTalentData)
.MAP(TopTalentData ::のgetName)
の.map(名- > name.length()== 10)
.orElse(TRUE)。
(nameNonExistentOrInvalidLength){もし
//いくつかの例外をスロー
}
topTalentService.addTopTalent(topTalentData)。
}

しかし、(貧しい建設を除く)は、上記の方法は、真の「クリーン」なソリューションではありません。私たちは、有効性の複数のタイプ(TopTalentDataは空にできませすなわち、TopTalentData.nameの長さは10文字まで空、そしてTopTalentData.nameではない)をチェックし、データが無効である場合に例外をスローしています。

データは、春にHibernateのバリデータを統合することによって、よりきれいであることが確認されています。復興addTopTalent方法の検証をサポートするために、最初にすべての私たちをみましょう:

@RequestMapping( "/ PUT")
公共ボイドaddTopTalent(@Valid @NotNull @RequestBody TopTalentData topTalentData){
topTalentService.addTopTalent(topTalentData);
}
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
パブリックはErrorResponse handleInvalidTopTalentDataException(MethodArgumentNotValidException methodArgumentNotValidException){
//ハンドル例外検証
}
//加えて、我々は我々が検証したいことを指摘しなければならないものをTopTalentDataクラスのプロパティ:
パブリッククラスTopTalentData {
@Length(= 10分、最大= 10)
@NotNull
プライベート文字列名;
}

さて、春には、その要求をインターセプトし、メソッドを呼び出す前に、パラメータを検証する - 追加の手動テストを使用せずに。

同じ機能を実現するもう一つの方法は、私たち自身のノートを作成することです。通常、あなたが使用カスタム注釈を休止制約のビルトインのセットを超えて行く必要があるときにのみが、このケースでは、我々は@Lengthが存在しないことを前提としています。あなたはコメントの検証属性の文字列の長さ、1を検証するために、2つの追加クラスを作成することができます。

@Target({ElementType.METHOD、ElementType.FIELD、ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {MyAnnotationValidator.class})
パブリック@interfaceのMyAnnotation {
文字列メッセージ()デフォルトの「文字列長「予想と一致しません。
<?>クラス[]グループ()デフォルト{}。
クラス<?ペイロード> []ペイロード()デフォルト{}延びています。
int値();
}
@Component
パブリッククラスMyAnnotationValidatorはConstraintValidator <MyAnnotation、文字列> {実装
プライベートint型expectedLengthと、
@Override
公共ボイドイニシャライズ(MyAnnotation myAnnotation){
this.expectedLength = myAnnotation.value()。
}
@Override
パブリックブールのisValid(文字列S、ConstraintValidatorContext constraintValidatorContext){
リターンS ==ヌル|| s.length()== this.expectedLength。
}
}

(ヌル==のisValidメソッド)それがアクティブとしてマークされ、これらのケースでは、ベストプラクティスは、プロパティを必要と関心事の分離がnullである、ということに注意してください、これは追加の要求特性である場合には、使用@NotNull注釈。

パブリッククラスTopTalentData { 
@MyAnnotation(値= 10)
@NotNull
プライベート文字列名。
}

7、エラー7 :(まだ)は、XMLベースの設定

春の以前のバージョンでは、XMLが必要ですが、今ほとんどの設定は、Javaコードや注釈を介して行うことができますが、単に追加の不要な定型的なコードとしてXMLコンフィギュレーションを。

(とそれに付随するのGitHubリポジトリ)本明細書中にスキャンする最上位のパッケージディレクトリが@SpringBootApplication複雑なノートの陳述をしたので、次のように、春、春の豆が接続されるべきかを知るために設定するには、アノテーションを使用しています。

@SpringBootApplication 
パブリッククラスのアプリケーション{
パブリック静的無効メイン(文字列[] args){
SpringApplication.run(Application.class、引数)。
}
}

コンポジットコメント(あなたは春のドキュメントでより多くを学ぶことができます)春のヒントにパッケージ化するだけでは、ビーンを取得するためにスキャンする必要があります。我々の場合には、これはトップレベルのパッケージ(co.kukurin)を取得するために使用されることを意味します。

  • @Component(Toptalentコンバータ、MyAnnotationValidator)
  • @RestController(Toptalentコントローラ)
  • @Repository(TopTalentRepository)
  • @Service(TopTalentService)类

我々は追加のコメント@Configurationクラスを持っている場合は、Javaベースの構成を確認します。

8、エラー8:無視プロフィール

サービス側の開発では、頻繁に遭遇する問題には、構成の異なる種類の、通常生産の構成と開発の設定を区別することです。テストからアプリケーションを展開するたびに切り替え、様々な構成が手動で入力する代わりにはなりませんが、より効果的な方法は、プロファイルを使用することです。推奨される読書:春ブートプロファイル異なる環境の構成。Javaテクノロジ・スタックマイクロチャネル公共数に焦点を当て、バックグラウンドキーワードに返信:ブーツを、あなたは長い間、乾燥、最新の技術を終え春ブーツのスタックを取得することができます。

このような状況を考えてみましょう:あなたは、地域開発のためのインメモリ・データベースを使用して、本番環境でのMySQLデータベースを使用しています。基本的に、これはあなたが両方にアクセスするために、異なるURL、および(うまくいけば)別の資格情報を使用する必要があることを意味します。あなたはそれ二つの異なるプロファイルを行うことができます方法を見てみましょう:

8.1。APPLICATION.YAMLファイル

'DEV'に#セットのデフォルトのプロファイル
spring.profiles.active:DEV
#の本番データベースの詳細は
spring.datasource.url: 'JDBCます。mysql:// localhostを:3306 / toptal'
spring.datasource.username:ルート
spring.datasource.passwordを:
8.2。APPLICATION-DEV.YAML文件
spring.datasource.url: 'JDBC:H2:MEM:'
spring.datasource.platform:H2

あなたがDEVにデフォルトの設定ファイルは、理にかなっているように、あなたは、コードを変更したときに誤って本番データベース上の任意の操作を実行したくないと仮定します。

その後、サーバー上で、あなたがJVMにプロファイルを上書きし、手動で-Dspring.profiles.active = PRODパラメータを提供することができます。また、また、所望のデフォルトのプロファイルに、オペレーティング・システム環境変数。

9.エラーナイン:依存性の注入を受け入れることができません

春の依存性注入のすべてのオブジェクトをスキャンして一緒にすべての必要な構成を接続することができ、適切な手段を用いて、これは、関係をデカップリングするのに便利ですがまたによってクラス間のないタイト、テスト容易になりますこのような何かをするように結合されました:

パブリッククラスToptalentコントローラー{ 
民間最終Toptalentサービス人材サービス。
公共Toptalentコントローラ(){
this.topTalentService Toptalent =新しいサービス()。
}
}

私たちは私たちの春の接続をしてみましょう:

パブリッククラスToptalentコントローラー{ 
民間最終Toptalentサービス人材サービス。
公共Toptalentコントローラ(Toptalentサービス人材サービス){
this.topTalentService =人材サービス。
}
}

グーグルのMisko Heveryは、依存性注入の詳細な説明を話し、「なぜ」、それでは、実際にそれを見てみましょう使用する方法です。関心事の分離(よくある間違い#3)では、我々はサービスとコントローラクラスを作成しました。

我々は正しい前提のTopTalentService行動のコントローラをテストするとします。私たちは、達成する代わりに、実際のサービスクラスの個別の設定を経由してシミュレートされたオブジェクトを挿入することができます。

@Configuration 
パブリッククラスSampleUnitTestConfig {
@Bean
公共TopTalentService topTalentService(){
TopTalentService topTalentService = Mockito.mock(TopTalentService.class)。
。Mockito.when(topTalentService.getTopTalent())thenReturn(
。Stream.of( "メリー"、 "ジョエル")マップ(TopTalentData ::新).collect(Collectors.toList()));
topTalentServiceを返します。
}
}

その後、我々は春SampleUnitTestConfigを伝えることによって、使用モックオブジェクトを注入するクラスとしてそれを設定することができます。

@ContextConfiguration(クラス= {SampleUnitTestConfig.class})

その後、私たちは、豆はユニットテストに注入コンテキストコンフィギュレーションを使用することができます。

10.エラー10:テストの欠如、または不適切なテスト

ユニットテストの概念は長い間の周りされているが、多くの開発者が「忘れる」ためにどちらかのように見えるが(それは時間「必要」でない場合は特に)、それを行うには、あるいは単に事実の後にそれを追加します。これはテストだけではなく、コードの正しさを検証する必要があるため、文書はまた、振る舞い方の異なるシナリオの下でプログラムする必要があり、明らかに望ましくありません。

Webサービスをテストするときの通信は通常、春のDispatcherServletを呼び出し、そしてあなたがHTTP経由でHttpServletRequestを実際に受信したときに何が起こるか見るために必要とされているので、のみまれ「純粋な」ユニットテストは、(それを「統合」のテストを行います)検証、配列、等を処理します。

JavaのDSLを簡素化するRESTアシュアード、テストRESTサービスは、MockMVCに、非常にエレガントなソリューションを提供することが示されています。依存性注入と、次のコードスニペットを考えてみましょう:

@RunWith(SpringJUnit4Cla *** unner.class)
@ContextConfiguration(クラス= {
Application.class、
SampleUnitTestConfig.class
})
パブリッククラスRestAssuredTestDemonstration {
@Autowired
プライベートTopTalentController topTalentController。
@Test
公共ボイドshouldGetMaryAndJoel()は例外をスロー{
//与え
MockMvcRequestSpecification givenRestAssuredSpecification = RestAssuredMockMvc.given()
.standaloneSetup(topTalentController)。
//とき
MockMvcResponse応答= givenRestAssuredSpecification.when()( "/ toptal /取得")を取得。
//次に
response.then()からstatusCode(200)。
response.then()体( "名前"、hasItems( "メリー"、 "ジョエル"))。

}

SampleUnitTestConfigクラスアナログ実装TopTalentControllerに接続TopTalentService、および他のすべてのクラスがスキャンアプリケーションパッケージ標準下位クラスパッケージディレクトリによって推論されます。RestAssuredMockMvcはただ軽量な環境を設定するために、および/ toptal / GETエンドポイントはGETリクエストを送信します。

おすすめ

転載: www.cnblogs.com/hulianwangjiagoushi/p/11289897.html