Загальний дизайн аналізатора файлів на Java за допомогою шаблону стратегії


14

Я працюю над продуктом, у якому відповідальність одного з модулів полягає в розборі XML-файлів та скиданні необхідного вмісту в базу даних. Незважаючи на те, що ця вимога полягає лише в аналізі XML-файлів, я хочу створити свій модуль розбору таким чином, щоб я могла підтримувати будь-які файли в майбутньому. Причиною такого підходу є те, що ми будуємо цей товар для конкретного клієнта, але плануємо продати його іншим клієнтам найближчим часом. Усі системи в екосистемі для поточного клієнта виробляють і споживають XML-файли, але це може не стосуватися інших клієнтів.

Що я спробував поки що? (Сьогодні) Маю на увазі таку конструкцію, яка базується на моделі стратегії. Я швидко записав код у затемнення, щоб передати свій дизайн, тому було б чудово, якщо інші аспекти, такі як правильний спосіб поводження з винятками, поки що ігноруються.

Парсер: Інтерфейс стратегії, що розкриває метод розбору.

 public interface Parser<T> {
        public T parse(String inputFile);
    }

* Причина використання загального параметра полягає в тому, щоб дозволити будь-який тип повернення, а також забезпечити безпеку типу під час компіляції.

ProductDataXmlParser Конкретний клас для розбору файлу product.xml, який містить інформацію про продукт. (за допомогою XMLBeans)

public class ProductDataXmlParser implements Parser<ProductDataTYPE> {

    public ProductDataTYPE parse(String inputFile) {
        ProductDataTYPE productDataDoc = null;
            File inputXMLFile = new File(inputFile);

        try {
            productDataDoc = ProductDataDocument.Factory.parse(inputXMLFile);
        } catch(XmlException e) {
            System.out.println("XmlException while parsing file : "+inputXMLFile);
        } catch(IOException e) { 
                 System.out.println("IOException while parsing file : "+inputXMLFile);
        }
        return productDataDoc.getProductData();
    }
} 

де : ProductDataTYPE і ProductDataDocument - це класи POMO XMlBean, створені за допомогою xsd та команди scomp.

Майбутнє

Якщо у мене в майбутньому буде розібраний файл product.txt, я можу визначити свій власний POJO під назвою ProductData, який міститиме необхідний вміст файлу. Тоді я можу створити конкретний клас під назвою ProductDataFlatFileParser, який реалізує інтерфейс Parser та метод розбору, заповнивши PODO ProductData для мене після розбору файлу.

Чи має сенс ця конструкція? Чи є явні недоліки в цій конструкції? Поки конструкція стоїть, я дозволяю конкретним класам визначати алгоритм для розбору файлу і дозволяю конкретному класу вирішувати, де розмістити дані. Дизайн, здається, більше залежить від об’єктів домену, а не від форматів файлів. Це погано? Будь-які вдячності щодо того, як я можу вдосконалити свій дизайн, будуть високо оцінені.


Чи не повинно програмне забезпечення давати абоненту знати, які формати файлів підтримуються? Як ваше програмне забезпечення знає, до якого аналізатора звернутися?
— tomdemuyt

Ви шукаєте зворотній зв'язок щодо свого дизайну , а не вашої реальної реалізації , тому це буде перенесено на програмістів, де це тематично.
— codeparkle

@tomdemuyt Подумайте про заводський зразок;)
— CKing

2
@bot Користувач SO, який сказав вам опублікувати це в Code Review, очевидно помилявся. Ви могли прочитати FAQ на сайті, перш ніж розміщувати його, "хтось сказав мені це зробити" - це насправді не вагома причина для того, щоб робити що-небудь. Ніхто не грає з ним пінг-понг, хтось зголосився на свій час і спробував знайти краще місце для нього, а не відверто закривати його (що було б дійсним варіантом, оскільки це поза темою для Code Review).
— янніс

2
Будь ласка, і не перехрещуйтесь. Ти робиш безлад, який ми маємо прибирати.
— Зірвано

Відповіді:


7

У мене є кілька проблем:

  1. Я би переконався, що вам справді потрібен загальний дизайн, перш ніж його втілити. Ви впевнені, що вам знадобляться типи файлів, крім XML? Якщо ні, то для чого їх код? Якщо з часом вам це знадобиться, ви зможете вдосконалити код у цей момент. Це не займе набагато більше часу, ви, ймовірно, матимете інші вимоги, які зроблять код схожим на те, що ви зараз пропонуєте, і вам, ймовірно, ніколи не потрібно буде його писати. Як кажуть, YAGNI (вам це вже не потрібно).
  2. Якщо вам справді потрібен загальний дизайн, і ви впевнені в цьому, то я б сказав, що Parser<T>це в основному добре. Я бачу дві можливі проблеми: (1) вона передбачає введення файлів - що робити, якщо ви намагаєтеся розібрати потік JSON, який ви отримали, наприклад, з відповіді HTTP? і (2) це не обов'язково забезпечує велику цінність, за винятком частини більшої загальної системи, де у вас є безліч різних типів аналізаторів для безлічі різних типів даних. Але я не переконаний, що вам потрібні такі великі загальні рамки. Зараз у вас просто дуже конкретний випадок використання, наскільки я можу сказати: розібрати XML-файл у список ProductDatas.
  3. Майже ніколи не годиться проковтнути винятки, як це робиш ProductDataXmlParser. Я б перетворив це на якийсь RuntimeExceptionнатомість.

1
Ми будуємо продукт, який спілкуватиметься з багатьма зовнішніми системами, тому, мабуть, було б корисно врахувати будь-який формат файлу / вводу. Відмінний момент про потік JSON. Саме тому я мав метод мого розбору в інтерфейсі Parser взяти параметр String замість параметра File. У моєму ProductDataXmlParser була невелика помилка, яку я виправив (Потрібно передати файл XserBean аналізатору). Ви також праві щодо ковтання винятків. Я швидко записав цей код у затемнення, щоб передати свій приклад на
— stackoverflow

ОК здорово. Я думаю, я б зробив параметр Parser InputStream замість String - це те, що я говорю. :) І приємно почути про виняток - я не був впевнений, чи це було вирізано з вашого фактичного коду чи просто зразок коду для StackOverflow.

1
Також щодо створення продукту, який буде спілкуватися з багатьма зовнішніми системами, я б вагався створити будь-який загальний код без конкретних вимог. Наприклад, поки у вас є щонайменше два типи об'єктів для розбору або два формати файлів, які вам потрібні, я б не робив загальний інтерфейс Парсера.

Я задумаюся над тим, що ви говорите. Я хотів би зазначити, що є 4 різні файли xml, що містять 4 різних типи даних для розбору. Дані про продукт - це лише один тип даних, який повинен споживати наша система / продукт.
— CKing

У мене є ще одне питання до вас. Я не збираюся використовувати контекст, який є частиною структури стратегії. Це буде добре? Я також позбавляюся від загальних параметрів і повертаю Object методом розбору в інтерфейсі Parser. Це уникає класів, які використовують Parser для оголошення з параметром типу.
— CKing

1

Ваш дизайн - не найкращий варіант. За вашим дизайном єдиний спосіб його використання:

ProductDataXMLTYPE parser = new ProductDataXmlParser<ProductDataXMLTYPE>().parse(input); 
ProductDataTextTYPE parser = new ProductDataTextParser<ProductDataTextTYPE >().parse(input);

Ми не можемо побачити надто велику користь із наведеного вище прикладу. Ми не можемо робити такі речі:

Parser parser = getParser(string parserName);
parser.parse();

Ви можете розглянути наступні два варіанти, перш ніж шукати загальний:

  • 1, той же вихід після розбору

Незалежно від того, звідки джерело даних, дані про продукт будуть мати той самий формат, перш ніж зберегти їх у базу даних. Це договір між клієнтом і вашим дамп-сервісом. Тому я припускаю, що у вас є той самий ProductData як вихід. Ви можете просто визначити інтерфейс:

public interface Parser {
    public ProductData parse(String inputFile);
}

Крім того, ви визначаєте ProductData як інтерфейс, якщо хочете його більш гнучким.

Якщо ви не хочете, щоб Парсер змішувався з даними. Ви можете розділити його на два інтерфейси:

public interface Parser {
     public void parse(String inputFile);
}
public interface Data {
    public ProductData getData();
}

І ваш аналізатор буде виглядати так:

public class XMLParser implements Parser, Data {} 
public class TextParser implements Parser, Data {}
  • 2, різний вихід після розбору

Якщо ProductData не схожий і ви хочете повторно використовувати інтерфейс Parser. Ви можете це зробити так:

public interface Parser {
   public void parse(String inputFile);
}

class XMLParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataXML getProductData();        
}

class TextParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataText getProductData();        
}

-2

На всякий випадок, якщо ви віддасте перевагу використовувати щось вже доступне, я створив java-бібліотеку під назвою JRecordBind, що базується на XMLSchema (підтримується JAXB).

Він народився для споживання / створення файлів фіксованої довжини, і, оскільки XMLSchema визначає їх структуру, ви можете використовувати його за допомогою простого JAXB для marshall / unmarshall XML-файлів


Я шукаю проект для реалізації загального аналізатора! Я не думаю, що ти правильно зрозумів моє питання. :)
— CKing
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.