質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

Q&A

解決済

2回答

6767閲覧

大量にあるバリデーションのクラス設計

lupus_dingo

総合スコア257

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

0グッド

3クリップ

投稿2018/02/21 05:38

大きなプロジェクトになると大量のチェック処理が必要な場合があると思いますが、
例えば複数のメソッドから呼ばれる可能性のある1000個の共通バリデーションがある場合、
皆さんならどのように設計するでしょうか?
ここでいうバリデーションはDBエラーを防ぐ単項目チェックではなく業務的なチェックを意味します。

ぱっと思い付くのは、以下のように全てのバリデーションの窓口となるクラスをひとつと、それぞれのバリデーションクラスを作るというやり方です。

BusinessException isXxx(){
return new Xxx.check();
}
このように処理を外だしすると簡単なJavadocと上下の空行も含めて8行くらいで収まると仮定して、窓口が1クラス(8x1000=8000行 +αくらい)と、バリデーションの1000クラスを作成することになりますが、正直1000行を越えるクラスですら作成することに違和感があります。

このような場合皆さんはどのようにクラス設計しているでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

DIなりリフレクションなり実装方法はいくつかあります。
デザインパンターンでもいくつか解決できると思います。

そもそもそんなにチェック処理が多いのであれば、
まずサブシステム化を検討したほうがいいでしょう。
おそらくいろんなシステムで同じチェックをしているはずです。

また大きすぎるプロジェクトよりは、
細かくサブシステム化するほうが、全ての工程においてメリットが大きいです。

追記

java

1interface Validation { 2 BusinessException check(); 3} 4class ValidationA implements Validation { 5 BusinessException check() { 6 //hogehoge 7 } 8} 9class ValidationB implements Validation { 10 BusinessException check() { 11 //hogehoge 12 } 13} 14class ValidationFactory { 15 static Validation newIncetance(String classname) { 16 try { 17 Class<?> clazz = Class.forname(classname); 18 return (Validation) clazz.newIncetance(); 19 } catch (Exception e) { 20 } 21 return new DefaultValidation(); 22 } 23} 24class BusinessLogic { 25 void logicA() { 26 Validation validation = ValidationFactory.newIncetance("ValidationA"); 27 validation.check(); 28 } 29 void logicB() { 30 Validation validation = ValidationFactory.newIncetance("ValidationB"); 31 validation.check(); 32 } 33}

タイポがあるかもしれません。

投稿2018/02/21 08:17

編集2018/03/02 06:14
szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2018/02/21 23:45

アドバイスありがとうございます。 実際はもっと少ないです。 例えで1,000と言いましたが大きく言い過ぎましたすみません。 ちなみにDI、リフレクションするとはどういうことでしょうか? 呼び出しは必要になるので窓口の行数的にはほとんど変わらないと思うのですが、その呼び出しを省略できるということでしょうか?
szk.

2018/02/22 02:02

DIは依存性注入、 リフレクションは動的にインスタンスを作成したり任意のメソッドを実行したりする方法です。 Factory内をリフレクションで返すようにして、 引数は依存性注入(DI)で設定すれば、 例外処理も含めて20行もなくて済むと思います。 interfaceクラスやabstractクラスについて理解されていますか?
lupus_dingo

2018/03/02 00:05

>interfaceクラスやabstractクラスについて理解されていますか? 上の例で言うと、バリデーション用のinterfaceを作ってXxxクラスでそれを実装するみたいな感じでしょうか? どのタイミングでどのバリデーションを呼び出すかを分岐を行わずに切り分けられるということでしょうか?
szk.

2018/03/02 06:14

> 上の例で言うと、バリデーション用のinterfaceを作ってXxxクラスでそれを実装するみたいな感じでしょうか? そういうことになります。 > どのタイミングでどのバリデーションを呼び出すかを分岐を行わずに切り分けられるということでしょうか? 具体的な話は、もう少し具体的なソースを提示いただかないとわかりません。 一応、適当なサンプルを書いてみましたが、、、 ちょっと簡単過ぎて、有用性が分かりづらいですね。 ただValidationAとValidationBの分岐はなくなりました。 「java factory」や「java reflection」で検索してもらったほうがいいかと思います。 ご参考までに1つ http://futurismo.biz/archives/2805
lupus_dingo

2018/03/04 10:20

なるほど。たしかにこれだとクラス1つと呼び出し1行(メソッドチェーンにした場合)が増えるだけですね。 デメリットとしては呼び出し元がeclipse とかで簡単には辿れなくなることでしょうか? それから呼び出す際は文字列よりクラス名.classを直接指定するほうが間違いなくて良さそうですね。
szk.

2018/03/05 00:51

IDE使っていればどうにかして追えます。 eclipseだと「Ctrl + Shift + R」でリソース検索できますし。 クラスを指定するのもいいんですが、 そうすると呼び出し元で対象のクラスをimportしないといけないですよね。 むしろ以下と変わらないことになります。  Validation validation = new ValidationA(); これで事足りるのであれば、問題ないかと思います。 依存性の注入として、文字列を指定しています。 文字列だったら、プロパティファイルなどに外出しできるので、 設定の変更が比較的容易にできます。 コンパイルやデプロイ、リリースも不要ですし。 ただ設定次第で挙動が変わるので、注意は必要になります。
lupus_dingo

2018/04/20 14:47

回答遅れてすみません。 たしかにimport文がいらないのは気付きませんでした。 ありがとうございます。助かりました。
guest

0

勿論例えばの話だとは理解していますが、1000もの共通バリデーションがあるという状況は明らかに要件過多なので、まずは削減する方向に持っていくというのが大前提ですね。そんなバリデーションを行ったとしても運用に耐えられずいずれ削減されるとしか思えません。

どうしても何かしらの多数の共通チェックが必要なのであれば、個々の業務処理から呼び出される共通クラスのようなもので都度チェックをするという前提を見直す必要を感じます。
完全に共通なチェック処理なのであれば、個々の業務処理から都度行う必要はないでしょう。
ひとまず共通チェックなしで処理を通し(例えばデータベースに格納し)、夜間処理や一定時間ごとのタスク処理で、格納されたデータを一気にチェックし、必要に応じて修正するという方針を検討します。

誤っている可能性のあるデータを反映することに抵抗があったとしても、いきなり本番データとして反映せず、一旦仮データとして保持し、チェックに通らなかったデータは仮データとして扱い続けるようにすれば、ほぼ問題ないでしょう。

それも無理な要件であれば、下手に凝ったクラス設計をすると余計に煩雑になりますので、せめてできるだけシンプルになるよう設計します。
例えば、可能であればチェック処理はstaticなクラス、メソッドにするなど。

投稿2018/02/21 07:42

akabee

総合スコア1947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2018/02/21 23:36

アドバイスありがとうございます。 たしかに1,000個は言い過ぎでした。 実際は半分に満たないくらいでサブシステム化されています。中には1,000を越えるようなプロジェクトもあるんじゃないかと思い質問しましたが、たしかにそもそも業務的に耐えられないですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問