Design pattern per l'elaborazione di un enorme file CSV - Java

5

Sto imparando modelli di progettazione in Java e sto anche lavorando su un problema in cui ho bisogno di gestire un numero enorme di richieste in streaming nel mio programma da un enorme file CSV sul disco. Ogni riga CSV è una richiesta e il primo campo in ogni riga indica il tipo di messaggio. Esistono 7 tipi di messaggi, ognuno dei quali dovrebbe essere gestito in modo diverso.

Il codice è simile al seguente:

class Handler {
    private CustomClass {….}
    Map<String, CustomClass> map = new HashMap<String, CustomClass>();
    Public void runFile() {
        // Read the huge CSV file with millions of records, line by line
        // for each line, get the string before the first comma (say X)
        switch (X) {
        case 1 : myMethod1(….); break;
        case 2 : myMethod2(….); break;
        case 3 : myMethod3(….); break;
        // ...
        default: // ...
        }
    }
    // Methods 1, 2, 3 declarations
}

Nota 1: alcuni dei metodi influenzano la mappa e altri no.
Nota 2: ogni richiesta (metodo) utilizza variabili diverse dalla linea CSV ed esegue una logica diversa.
Nota 3: richieste / metodi NON sono collegati; vale a dire myMethod2() non segue logicamente myMethod1() .

Ora la mia domanda: qual è uno schema di progettazione appropriato per questo problema? Va bene se tengo l'intera logica in una classe (simile al codice sopra) senza cambiare?

    
posta Shad 24.06.2017 - 03:05
fonte

2 risposte

5

Presumo che l'esempio di codice che mostri sia solo un esempio semplificato e che il vero problema sia più complesso, così da meritare l'utilizzo di un modello.

  • Crea CustomClass una classe esterna (*).
  • avere diversi processori che implementano la stessa interfaccia
  • Avere una mappa dei processori che usa il numero intero che identifica il formato della linea CSV come chiave (la si chiama x).
  • Recupera un processore dalla mappa (con la chiave correspoding) e falla elaborare la linea.
  • Questo simile al modello di strategia , definisce una famiglia di algoritmi, incapsula ciascun algoritmo e rende gli algoritmi intercambiabili all'interno di quella famiglia.

Vantaggi: flessibilità, se crei la mappa dei processori all'esterno del gestore e la passi nel costruttore, più processori possono essere aggiunti in seguito e Handler non dovrà essere modificato (ad esempio per aggiungere un nuovo caso la struttura di controllo dell'interruttore).

(*)Èpossibileottenereglistessirisultaticonl'interfaccia,iprocessorielaclassepersonalizzatacomeclassiinterne/interfacceall'internodiHandler,mainquinerebbemoltolasoluzione.

==>CustomClass.java<==

public class CustomClass {}

== > IMessageProcessor.java < ==

import java.util.Map;

public interface IMessageProcessor {
    public void processLine(Map<String, CustomClass> map, String line);     
}

== > ProcessorA.java < ==

import java.util.Map;

public class ProcessorA implements IMessageProcessor {
    @Override
    public void processLine(Map<String, CustomClass> map, String line) {
        // TODO Auto-generated method stub
    }
}

== > ProcessorB.java < ==

import java.util.Map;

public class ProcessorB implements IMessageProcessor {
    @Override
    public void processLine(Map<String, CustomClass> map, String line) {
        // TODO Auto-generated method stub
    }
}

== > ProcessorC.java < ==

import java.util.Map;

public class ProcessorC implements IMessageProcessor {
    @Override
    public void processLine(Map<String, CustomClass> map, String line) {
        // TODO Auto-generated method stub
    }
}

== > Handler.java < ==

import java.util.HashMap;
import java.util.Map;

public class Handler {
    private Map<String, CustomClass> map = new HashMap<String, CustomClass>();
    private Map<Integer,IMessageProcessor> processors = new HashMap<Integer,IMessageProcessor>();
    public processFile(){
        // store the processors in their map with the appropiate keys 
        processors.put(1, new ProcessorA());
        processors.put(2, new ProcessorB());
        processors.put(3, new ProcessorC());

        // Read the huge CSV file with millions of records, line by line
        // for each line, get the string before the first comma (say x)
        processors.get(x).processLine(map,line);
    }
}

Nota: potresti voler prima convalidare se il processore per la chiave x esiste, e non lo fa, ricorrere a un processore predefinito, ad esempio, memorizzato con la chiave -1, o qualsiasi altro valore garantito per non esistere nel file CSV.

    
risposta data 24.06.2017 - 04:30
fonte
5

Keep It Simple, Stupid (KISS)

What is an appropriate design pattern for this problem? Is it fine if I keep the whole logic in one class (similar to the code above) without changing?

Sì, lascia tutta la logica in quella classe. Non cercare di applicare modelli di design esotici solo perché i modelli di design sono eleganti. L'unica cosa che realizzerai con un modello di progettazione è rendere le cose complicate in modo non appropriato.

    
risposta data 24.06.2017 - 04:12
fonte