Когда дублирование кода является правильным решением
От: 0K Ниоткуда  
Дата: 24.04.11 23:32
Оценка:
Всегда раньше считал что дублирование кода -- это плохо (без всяких исключений).

Но оказывается есть случаи когда дублирование кода -- наиболее правильно решение.

Случай, благодаря которому я пришел к такому вывод -- маппинг данных.

Мне нужно было данные из базы Amazon SimpleDB проецировать (ну или мапить) на объекты высокоуровневого языка. Т.е. нужно было сохранять объекты в базу и воссоздавать объекты из данных БД.

Первое решение, которое пришло в голову -- использовать рефлексию. Кстати, даже есть готовые библиотеки работающие по этому принципу.

Но при разборе больших массивов данных -- рефлексия работает медленно.

Наиболее подходящим решением оказалась КОДОГЕНЕРАЦИЯ. Причем это решение оказалось на порядок проще рефексии.

В итоге получился такой код для авто-генерации:

        final String lineSeparator = System.getProperty("line.separator");

        Field[] fields = entityClass.getDeclaredFields();
        StringBuilder stringBuilder = new StringBuilder();

        // object->item
        stringBuilder.append("protected RequestAttributeContainer buildRequestAttributeContainer()" + lineSeparator);
        stringBuilder.append("{" + lineSeparator);
        stringBuilder.append("RequestAttributeContainer requestAttributeContainer = new RequestAttributeContainer();" +
            lineSeparator);

        {
            for (Field field : fields)
            {
                String fieldName = field.getName();
                stringBuilder.append("requestAttributeContainer.addAttribute(\"" + fieldName + "\", " + fieldName +
                    ");" + lineSeparator);
            }
        }

        stringBuilder.append("return requestAttributeContainer;" + lineSeparator);
        stringBuilder.append("}" + lineSeparator);

        // item->object
        stringBuilder.append(lineSeparator);

        stringBuilder.append("protected " + entityClass.getSimpleName() +
            "(ResponseAttributeContainer responseAttributeContainer)" + lineSeparator);
        stringBuilder.append("{" + lineSeparator);

        {
            for (Field field : fields)
            {
                String fieldName = field.getName();
                Class<?> fieldType = field.getType();

                String suffix;

                if (fieldType.equals(boolean.class))
                {
                    suffix = "AsBoolean";
                }
                else if (fieldType.equals(int.class))
                {
                    suffix = "AsInteger";
                }
                else if (fieldType.equals(long.class))
                {
                    suffix = "AsLong";
                }
                else if (fieldType.equals(String.class))
                {
                    suffix = "";
                }
                else
                {
                    suffix = "As" + fieldType.getSimpleName();
                }

                stringBuilder.append(fieldName + " = responseAttributeContainer.tryGetAttributeValue" + suffix + "(\"" +
                    fieldName + "\");" + lineSeparator);
            }
        }

        stringBuilder.append("}" + lineSeparator);

        System.out.print(stringBuilder.toString());


Он создает 2 метода: buildRequestAttributeContainer и конструктор класса. В этих методах происходит проекция объекта (кое-какая логика вынесена в общие классы).

Как видите -- получилось очень и очень просто, на порядок проще использования рефлексии, а скорость заметно возросла.

Какие недостатки у подобного решения?
Re: Когда дублирование кода является правильным решением
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.04.11 23:47
Оценка:
Здравствуйте, 0K, Вы писали:

0K>В итоге получился такой код для авто-генерации:


Причем тут дублирование кода? Где ты его усмотрел?

0K>Какие недостатки у подобного решения?


При усложнении генератора (особенно усложнении логики) он превратится в кашу. Он уже ею является.
Потом может случится так, что ты найдешь баг в сгенерированном коде и забыв что он генерирован поправишь его. После очередной перегенерации ты потеряешь изменения и получишь ошибку снова.

Кроме того кода находишь ошибку в сгенерированном коде (и знаешь что он сгенерирован) нужно искать участок генератора его породивший. Если объем генератор большой — это проблема.

Но это все проблемы твоего дремучего подхода. Кроме него существуют и более продвинутые. Например, использование T4. Его проблемой является то, что он генерирует текст, а в нем легко ошибиться. Еще более продвинутый подход использование макросов. Для них зачастую и рефлексия не нужна. Но тут уже нужен специализированный язык.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Когда дублирование кода является правильным решением
От: adontz Грузия http://adontz.wordpress.com/
Дата: 24.04.11 23:55
Оценка:
Здравствуйте, 0K, Вы писали:

0K>Какие недостатки у подобного решения?


В способе реализации. Ты не должен редактировать код генератора напрямую, иначе котеряешь контроль над ситуацией очень скоро.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Когда дублирование кода является правильным решением
От: jazzer Россия Skype: enerjazzer
Дата: 25.04.11 01:40
Оценка: +4
Здравствуйте, 0K, Вы писали:

0K>Наиболее подходящим решением оказалась КОДОГЕНЕРАЦИЯ. Причем это решение оказалось на порядок проще рефексии.


Кодогенерация — это не дублирование кода
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.