Загальний дизайн аналізатора файлів на 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.