Quali sono gli schemi di progettazione rilevanti per eseguire convalide su un oggetto?

0

Ho un tipico caso d'uso in cui sto consumando un broker di messaggi. I messaggi sono < ^ > stringhe delimitate. Analizzo ogni singolo messaggio creando POJO e quindi applicando diverse convalide per capire se il messaggio è utile per ulteriori elaborazioni. Chiamiamo queste convalide come filtri.

Questi filtri sono creati dinamicamente dagli utenti delle applicazioni e questi filtri devono essere applicati dinamicamente ai messaggi in arrivo.

A partire da ora sto convalidando i messaggi usando i loop di IF-ELSE. Ma, vorrei verificare se ci sono schemi di progettazione che stanno già rendendo elegante questa affermazione problematica.

Un filtro tipico ha una FilterCriteria che parla delle Condizioni che devono essere verificate rispetto a un messaggio.

Codice:

// load filters for a given party and apply on the rawSyslogMessage.
    private boolean applyFilter(RawSyslogMessage message) throws EntityNotFoundException {

        boolean isDropped = false;

        logger.info("---applyFilter()::rawSyslog :" + message);

        String partyID = message.getPartyID();

        // load all filters for the given party
        List<Filter> filters = filterService.getAll(partyID);

        if (filters != null) {
            for (Filter filter : filters) {

                FilterCriteria filterCriteria = filter.getFilterCriteria();
                String field = filterCriteria.getField();
                String condition = filterCriteria.getCondition();
                String action = filterCriteria.getAction();

                // FILTER. Consider applying all fitlers on a message.
                if (filter.getName().toUpperCase().equals("PRIORITY") && action.toUpperCase().equals("ALLOW")) {
                    if (condition.toUpperCase().equals("GREATER")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else {
                            logger.info("The message is sent for correlation");
                        }
                    } else if (condition.toUpperCase().equals("LESSER")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is sent for correlation");
                        } else {
                            logger.info("The message is dropped");
                            isDropped = true;
                        }
                    } else if (condition.toUpperCase().equals("EQUALS")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is sent for correlation");
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else {
                            logger.info("The message is dropped");
                            isDropped = true;
                        }
                    } else if (condition.toUpperCase().equals("BETWEEN")) {
                        String[] range = field.split("TO");
                        String _left = range[0];
                        String _right = range[1];
                        if (message.getSeverity() >= Integer.parseInt(_left)
                                && message.getSeverity() <= Integer.parseInt(_right)) {
                            logger.info("The message is sent for correlation");
                        } else {
                            logger.info("The message is dropped");
                            isDropped = true;
                        }
                    }
                } else if (filter.getName().toUpperCase().equals("PRIORITY")
                        && action.toUpperCase().equals("DISCARD")) {
                    if (condition.toUpperCase().equals("GREATER")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is sent for correlation");
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is sent for correlation");
                        } else {
                            logger.info("The message is dropped");
                            isDropped = true;
                        }
                    } else if (condition.toUpperCase().equals("LESSER")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is sent for correlation");
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else {
                            logger.info("The message is sent for correlation");
                        }
                    } else if (condition.toUpperCase().equals("EQUALS")) {
                        if (Long.toString(message.getSeverity()).equals(field)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else if (message.getSeverity() < Long.parseLong(field)) {
                            logger.info("The message is sent for correlation");
                        } else {
                            logger.info("The message is sent for correlation");
                        }
                    } else if (condition.toUpperCase().equals("BETWEEN")) {
                        String[] range = field.split("TO");
                        String _left = range[0];
                        String _right = range[1];
                        if (message.getSeverity() >= Integer.parseInt(_left)
                                && message.getSeverity() <= Integer.parseInt(_right)) {
                            logger.info("The message is dropped");
                            isDropped = true;
                        } else {
                            logger.info("The message is sent for correlation");
                        }
                    }
                }
            }
        }

        return isDropped;
    }

Ho fatto riferimento a

link (come suggerito in Stile per il controllo del flusso con controlli di validazione )

link

link

Ma nessuno di questi sembra corrispondere alle mie esigenze. Per favore aiuto.

    
posta wandermonk 05.01.2018 - 12:20
fonte

4 risposte

2

Dai uno sguardo a Pattern di intercettazione del filtro , potrebbe essere adatto al tuo scopo. Fornisce flessibilità ed estensibilità per la possibilità di creare nuovi tipi di filtri e può essere utilizzato per associare le combinazioni di filtri desiderate per attività specifiche.

    
risposta data 05.01.2018 - 13:54
fonte
0

Bene, il miglioramento più ovvio sarebbe che anziché la classe Filter è solo una borsa di proprietà, e il tuo singolo metodo lungo che fa le basi di filtraggio su queste proprietà, "Filtro" sarebbe un'interfaccia e avresti sottoclassi che la implementano ciò includerebbe il codice effettivo per l'esecuzione di ciascun tipo di filtro.

Non sono sicuro di quale sarà il modello di progettazione, probabilmente il modello di strategia, che hai già menzionato. Che dire di quel modello ti fa pensare che non corrisponde ai tuoi requisiti?

    
risposta data 05.01.2018 - 14:58
fonte
0

Un altro approccio da adottare è usare monad s per mantenere il risultato della convalida. Una buona panoramica dell'approccio è fornita in Dati funzionali Validazione tramite monadi e funtori applicativi . Fondamentalmente, l'oggetto monad contiene il risultato validato o un messaggio di convalida che può essere registrato o utilizzato per un feedback più utile.

Ad esempio, utilizzando una delle monade Try per Java:

Try<String> validatedCondition = Try.apply( () -> validateCondition( condition ) );
Try<String> validatedField = Try.apply( () -> validateField( field ) );
...
if ( validatedFilterCriteria.isSuccess() &&
     validatedCondition.isSuccess() &&
     validatedField.isSuccess() ) {
  // now operate on the validated values
}
else {
  // a validation failed, so extract the failure message
  Try<String> result = validatedFilterCriteria
     .andThen( validatedCondition )
     .andThen( validatedField );
  log.error( "Validation failure: " + result.failureMessage() );
}

...
private String validateCondition( String condition ) {
  assert condition != null;
  assert !condition.isEqual("");
  ...
  if ( condition.isValid() ) {
     return condition;
  }
}
... // similarly for other validations

Mentre Java è molto più dettagliato di Scala, puoi realizzare la stessa cosa e ottenere convalide più sistematiche.

    
risposta data 05.01.2018 - 15:15
fonte
0

Una combinazione di decori e modelli di strategia è stata un'ottima soluzione per me quando si gestiscono i questionari scansionati.

La convalida è una strategia creata da una o più strategie decorate l'una attorno all'altra.

L'utente può quindi selezionare ciascuna strategia disponibile e l'ordine di ciascuna strategia (cioè l'ordine di come sono decorate le strategie).

    
risposta data 05.01.2018 - 15:29
fonte

Leggi altre domande sui tag