Когда дублирование кода является правильным решением
От: 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 и конструктор класса. В этих методах происходит проекция объекта (кое-какая логика вынесена в общие классы).

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

Какие недостатки у подобного решения?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.