-1

I currently have two ways of processing basically the same data (it is in a slightly different format and cannot(!) be converted between each other). Since both imports share so much logic most of it is kept in AbstractImporter. I extend this class for the new and old behavior and the resulting two classes are used by their respective processors.

The processor may or may not be called by a batch but as you can see down below I cannot use the same interface as they accept different inputs (the new logic uses CsvLines - which are converted into ImportLines - while the legacy logic uses its own iterator and already prepared ImportLines). I really don't like not having a common interface that I can use (I'm using the CsvProcessor interface - but the implementation is empty for the legacy code) and having a processor which is just calling and importer (whatever that is) seems just stupid and cumbersome.

This complexity is now causing some weird issues (which are beyond the scope of this question) but it is still a big improvement to the old code as this was just one big monster controller (unbulkified and entangled with UI logic) so at least there's that.

Still - I think the current classes suck but I'm totally confused how to split the responsibilities better or how to build a common interface (if possible). In an ideal world I would just have one entry point that I call from the UI or a batch or whatever.

For my brain this is way too much for a Friday so - if anybody wants to chime in that would be great!

Legacy processing:

(new LegacyProcessor(importOptions)).processLines(lineIterator, importLines);

New processing:

(new Processor(importOptions)).processLines(csvLines);

AbstractImporter (encapsulates most of the logic)

public abstract class AbstractImporter {
    private ImportOptions importOptions;

    public AbstractImporter(ImportOptions importOptions) {
        this.importOptions = importOptions;
    }

    public void loadData(Set<String> postalCodes) {
    }

    protected void processLine(LineWrapper lineWrapper) {
    }

    public void persist() {
    }
}

LegacyImporter (pretty much what the abstract class already does)

public class LegacyImporter extends AbstractImporter {
    public Importer(ImportOptions importOptions) {
        super(importOptions);
    }

    public void process(LineWrapper lineWrapper) {
        this.processLine(lineWrapper);
    }
}

Importer (basically LegacyImporter with some additional processing)

public class Importer extends AbstractImporter {
    public Importer(ImportOptions importOptions, Boolean hasOption) {
        super(importOptions);

        // Do some initialization
    }

    public void cloneStuff(Integer lineCount) {
        // Do some stuff before processing
    }

    public void process(CsvLine csvLine, Boolean hasOption) {
        LineItem lineItem = createLineItem();

        ImportLine importLine = new ImportLine(csvLine);

        this.processLine(new LineWrapper(importLine, lineItem));
    }
}

LegacyProcessor (using LegacyImporter - similar iteration as in other processor)

public class LegacyProcessor implements CsvProcessor {
    private ImportOptions importOptions;

    public LegacyProcessor(ImportOptions importOptions) {
        this.importOptions = importOptions;
    }

    public void processLines(List<CsvLine> lines) {
        // Processing
    }

    // This is used instead of the method above!
    public void processLines(LineIterator lineIterator, List<ImportLine> importLines) {
        LegacyImporter importer = new LegacyImporter(this.importOptions);

        // Load some data
        importer.loadData(this.getPostalCodes(importLines));

        // Actual processing
        while (lineIterator.hasNext()) {
            importer.process(lineIterator.next());
        }

        importer.persist();
    }
}

Processor (using Importer - similar iteration as in other processor)

public class Processor implements CsvProcessor {
    private ImportOptions importOptions;

    public Processor(ImportOptions importOptions, String moreParameters) {
        this.importOptions = importOptions;
    }

    public void processLines(List<CsvLine> lines) {
        Importer importer = new Importer(this.importOptions, true);

        // Processing

        // Load some data
        importer.loadData(this.getPostalCodes(lines));

        // Additional preparation
        importer.cloneStuff(lines.size());

        // Actual processing
        for (CsvLine line : lines) {
            importer.process(line);
        }

        importer.persist();
    }
}

closed as too broad by Jayant Das, battery.cord, codeyinthecloud, David Reed, glls Jan 12 at 2:56

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.