2016-12-19 7 views
1

私はいくつかのフィールドで検証する必要がある2つの処理を持っています。入力を検証し、それに応じてアクションを実行します

  • クラスクラスの場合、いくつかのフィールドで検証する必要があります。これらのフィールドに基づいて、私はこのクラスを検証します。
  • ProcessBクラスの場合は、別のフィールドで検証する必要があります。これらのフィールドが有効な場合は、このクラスを検証します。

どちらも私のプロセスはGenericRecordValidatorにクラスを渡す必要がありますし、今ではProcessAProcessBであるかどうかに応じて、私のValidatorクラスは、これらのフィールドを検証する必要があります。

  • はProcessAについては、私はclientIddeviceIdpayIdに検証する必要があります。
  • ProcessBについては、crossIdmaxIdminIdで検証する必要があります。

は、私はそれがProcessAのために動作させることが可能ですが、私は私のValidatorクラスはProcessBフィールド検証のためのようになりますどのように混乱しています。コンストラクターでGenericRecordを受け取るとすぐにValidatorクラスがProcessAまたはProcessBのフィールドを検証する必要があると判断して混乱させます。 ProcessA GenericRecordが渡された場合は、ProcessAフィールドで検証を行うか、ProcessB GenericRecordが渡された場合は、ProcessBフィールドで検証を行います。以下は

ProcessA

try { 
    GenericRecordDomainDataDecoder decoder = new GenericRecordDomainDataDecoder(config); 
    while (true) { 
    ConsumerRecords<byte[], byte[]> records = consumer.poll(1000); 
    for (ConsumerRecord<byte[], byte[]> record : records) { 
     GenericRecord payload = decoder.decode(record.value()); 
     String processName = "processA"; 
     // validation logic 
     Validator validation = new Validator(payload); 
     if(!validation.isValid()) 
      continue; 

     // some other code 
    } 
    } 
} catch (Exception ex) { 
    // logging error 
} 

ProcessB

try { 
    GenericRecordDomainDataDecoder decoder = new GenericRecordDomainDataDecoder(config); 
    while (true) { 
    ConsumerRecords<byte[], byte[]> records = consumer.poll(1000); 
    for (ConsumerRecord<byte[], byte[]> record : records) { 
     GenericRecord payload = decoder.decode(record.value()); 
     String processName = "processB"; 
     // validation logic 
     Validator validation = new Validator(payload); 
     if(!validation.isValid()) 
      continue; 

     // some other code 
    } 
    } 
} catch (Exception ex) { 
    // logging error 
} 

だけProcessA検証のために今働く私のValidatorクラスです。私は、私が動作しないことを知っている別のコンストラクタを追加しましたが、ちょうどProcessBのために何をしたいのかを示したかったのです。そして、私はisValidメソッドを呼び出して、ProcessBのフィールドが存在するかどうかを教えてくれます。

public class Validator { 
    private String clientId, deviceId, payId; 

    // for ProcessA 
    public Validator(GenericRecord payload) { 
    clientId = (String) DataUtils.parseRecord(payload, "clientId"); 
    deviceId = (String) DataUtils.parseRecord(payload, "deviceId"); 
    payId = (String) DataUtils.parseRecord(payload, "payId"); 
    } 

    // for ProcessB, I know this doesn't work - just wanted to show the idea 
    public Validator(GenericRecord payload) { 
    crossId = (String) DataUtils.parseRecord(payload, "crossId"); 
    maxId = (String) DataUtils.parseRecord(payload, "maxId"); 
    minId = (String) DataUtils.parseRecord(payload, "minId"); 
    } 

    // this is what I am calling for ProcessA 
    public boolean isValid() { 
    return isValidClientIdDeviceId() && isValidPayId(); 
    } 

    private boolean isValidPayId() { 
    if (payId == null) { 
     logger.log("invalid payId."); 
     return false; 
    } 
    return true; 
    } 

    private boolean isValidClientIdDeviceId() { 
    if (clientId == null && deviceId == null) { 
     logger.log("invalid clientId and deviceId."); 
     return false; 
    } 
    return true; 
    } 

    // getters 
} 

私はValidatorクラスに文字列である別のパラメータprocessNameを渡すことができます。それに応じてフィールドを検証するために、これを達成するためにこれを使用できますか?

答えて

1

私があなたに提案する最初の解決策は、Processクラスのタイプがほとんどない場合は受け入れられます。

コンストラクタを空にして、コンストラクタの後に呼び出すProcessによってinitメソッドを持つことができます。

ただ、デフォルトコンストラクタ(のことを宣言する必要はありません)を保持:この最初の

Validator validation = new Validator(); 
    validation.initProcessB(payload); 

:プロセスBでは

Validator validation = new Validator(); 
    validation.initProcessA(payload); 

:プロセスAで

public Validator() { 
    } 

    // for ProcessA 
    public initProcessA(GenericRecord payload) { 
    clientId = (String) DataUtils.parseRecord(payload, "clientId"); 
    deviceId = (String) DataUtils.parseRecord(payload, "deviceId"); 
    payId = (String) DataUtils.parseRecord(payload, "payId"); 
    } 

    // for ProcessB, 
    public void initProcessB(GenericRecord payload) { 
    crossId = (String) DataUtils.parseRecord(payload, "crossId"); 
    maxId = (String) DataUtils.parseRecord(payload, "maxId"); 
    minId = (String) DataUtils.parseRecord(payload, "minId"); 
    } 

をソリューションには限界があります。
Processクラスに依存する検証の特殊性がある場合は、より保守性が高いため、各プロセスの個別のバリデータークラスを使用してルールを分解することをお勧めします。

あなたは、たとえばかもしれない:プロセスAのための

public abstract class Validator<T extends Process>{ 

    ... 
    // common and abstract methods  
    ... 
    public abstract boolean isValid(); 
} 

バリA:プロセスBのための

public class ValidatorA extends Validator<ProcessA>{ 
    ... 
     public ValidatorA(GenericRecord payload){ 
      clientId = (String) DataUtils.parseRecord(payload, "clientId"); 
      deviceId = (String) DataUtils.parseRecord(payload, "deviceId"); 
      payId = (String) DataUtils.parseRecord(payload, "payId"); 
     } 

     public boolean isValid(){ 
      // validation rules specific to ProcessA 
     } 
    ... 

} 

バリB:

public class ValidatorB extends Validator<ProcessB>{ 
    ... 
     public ValidatorB(GenericRecord payload) { 
     crossId = (String) DataUtils.parseRecord(payload, "crossId"); 
     maxId = (String) DataUtils.parseRecord(payload, "maxId"); 
     minId = (String) DataUtils.parseRecord(payload, "minId"); 
     } 

     public boolean isValid(){ 
      // validation rules specific to ProcessB 
     } 

    ... 
} 
+0

最初のソリューションでは、私のない方法をisValidメソッドは次のようになりますか?私はisValidを意味するので、ProcessAまたはProcessBのフィールドを検証する必要があることも知っておく必要がありますか?実際のコードでは – john

+0

、 'isValid()'は両方のプロセスに共通です。それが望ましくない場合は、抽象的なValidatorクラスと、Processのタイプ別の具体的なValidatorクラスがある2番目のソリューションに従うべきだと思います。このようにして、それぞれの具体的なValidatorクラスで検証のために必要な特異性を定義することができます。 – davidxxx

+0

'isValid()'は両方のプロセスに共通することがあります。混乱は私が 'initProcessB'をしたとしましょう。そうすれば、isValidメソッドはProcessBだけのフィールドを検証するはずです。今すぐProcessAのフィールドを検証します。したがって、processBのinitを使用する場合、processBのコードからisValidを呼び出して、processBのフィールドを検証するisValidを呼び出すことができます。私のプロセスの両方に共通のフィールド検証はありません。それらはすべて異なります。 – john

関連する問題