понедельник, 12 июля 2010 г.

Сложность vs дублирование

Предпоследняя моя задачка в GGA была весьма символичной.

Краткое описание проблемы. Есть около года кодируемая форма в духе treetable. Работа с данными организована следующим образом: с сервера приходят какие-то структуры, они конвертируются во что-то типа встраиваемой RDB и она подкладывается как модель этой форме. Это буйство технологии несло в себе следующие проблемы:
  • Всё, в смысле 80% логики приложения - один класс. (банальность)
  • Работа с данными не читабельна на корню. (банальность)
  • То, что приходит с (ну потом и уходит на) сервера совпадает с тем, что хранит модель процентов на 60. Что-то вычисляется, что-то нужно для работы самой формы, назначение чего-то никто не знает. (сабж)
Последний пункт вызывал проблемы косвенно, но весьма изрядные: и в модели формы и в структурах, которыми общался сервер был ряд полей реально не используемых на разных этапах жизни этих данных. Кое-что перекладывалось из одного поля в другое в некоторые волшебные моменты времени. В общем удержать в голове что-откуда-куда-зачем было абсолютно нереально.

И вот мне была поставлена задача создать новую модель данных для формы и и продумать какую-то кхм... ну пускай архитектуру для работы с данными. Причём предполагалось добавление альтернативных отображений тех-же данных - с каким-то комбинированием полей, новыми вычислимыми полями и т.п.

Мысль мне пришла достаточно быстро: ввести 3 уровня.
  1. Структуры для взаимодействия с сервером, просто структуры.
  2. Доменные классы. Несущие только то, что необходимо для операций над данными и показа пользователю.
  3. Классы модели для конкретных представлений. Отображение второго уровня под нужны конкретного представления и локально-значимые поля.
И вроде-бы всё хорошо - уровни выделены, для каждой функции боле-менее понятно где она должна лежать, количество информации для единовременного хранения в памяти программиста должно резко пойти на убыль. Вот только повторяются структуры на этих уровнях процентов на 80. Одно и то же поле ObjName, именно оно самое, с нулевой семантической вариацией повторяется 3, а в перспективе и больше раз.

Альтернатива совсем очевидна - дополнить структуры используемые при общении с сервером недостающими полями и логикой. Повторений нет, но один и тот-же класс использовался бы в нескольких местах абсолютно по-разному.

Так что-же получается: выбор дублирование или разрыв мозга? Может есть решение без таких крайностей? Я не нашёл :(

Ещё интересно кто какой вариант выбрал бы в такой ситуации?

суббота, 12 июня 2010 г.

Немного мыслей о тестировании и тестерах

Последние пара дней отличились интенсивностью общения с группой тестирования, что повлекло ряд мыслей...

Во-первых, какие задачи решают баг-репорты:
  1. Идентификационную. Если у нас есть какая-то штука, то мы должны уметь посмотреть на другую и сказать "она такая-же" или "она другая". Тут надо понимать, что имеется в виду не просто уникальная цифра, а именно возможность имея перед глазами какую-то картину, пусть и с затратами, понять сталкивались ли мы с этим раньше(хотя цифра тоже не лишняя: с ней мы изрядно экономим на трафике и длине логов в месенджерах).
  2. Документирующую ака историческую. В проекте всё должно быть записано. Потомки должны знать ошибки предыдущих поколений, и знать, что это ошибки, и иметь возможность их найти позже.
  3. Коммуникативную. Крайнее Ответственное лицо должно узнать о том, что что-то "не так". Мало того узнав оно должно не бежать в соседнюю комнату или ждать пока к нему подойдут, чтобы потыкать пальцем в монитор. Оно должен после прочтения брать и воспроизводить проблему.
Далее, как метко подмечает товарищ Сartmendum основная боевая мощь живых тестеров сконцентрирована в двух фичах:
  1. Способности "смотреть по сторонам". То есть замечать окружение ошибки и передавать важные его особенности.
  2. Написании репортов на "человеческом языке". То есть рассказывать не что падает, а как падает.
А теперь, проникнувшись важностью процесса тестирования и благородной миссией людей его выполняющих, закрываем глаза и представляем баг из одного скриншота (в jpg кстати, но это другая история...) с обведённым в пейнте каким-то полем и комментарием типа: "Illegal status of nuclear fusion reactor"... 

Грустно. Сколько задач решает такая штука? А сколько времени убивается на то, чтобы эти задачи всё-таки решить?

А сколько заняло бы создание нормального описания ошибки?

четверг, 25 февраля 2010 г.

Что интересно спросить у работодателя

Анализ, общение с пользователями

  • Откуда берутся требования?
    • Как оценивается их выполнение?
  • Требования пересматриваются?
    • По каким причинам?
  • Как часто пользователь получает результаты работы?
  • Участвуют ли пользователи и эксперты в разработке?
    • В каких формах?
  • Что предпринимается в случае выявления противоречивости требований?

Процесс, планирование

  • Как формируются задачи на основе требований?
    • Как оцениваются сроки их выполнения?
  • Что предпринимается в случае невозможности выполнения требований по
    • техническим причинам?
    • организационным причинам?
    • экономическим причинам?

Программирование

  • Какая VCS используется? Почему?
  • Есть-ли стандарт кодирования?
    • Какие аспекты кода он регламентирует?
    • Как контроллируется его соблюдение?
  • Сколько человек видят/рецензируют код до его попадания в production?
    • Как это обеспечивается?
    • Обязательно-ли исправление по итогам сбора отзывов?
  • Как происходит сборка продукта?
  • Есть-ли система автоматической сборки?
    • Какие действия она предпринимает в случае успеха/неудачи сборки?
  • Имеет-ли разработчик в своём распоряжении полный стенд разрабатываемого продукта или какие-то его части?
    • Этот стенд изолирован от других разработчиков?

Контроль качества, тестирование

  • На какие уровнях производится тестирование?
    • Как каждый из них автоматизирован?
  • Есть-ли люди ответственные за контроль качества?
    • Сколько их от общего числа разработчиков?
    • Какие задачи они решают?

среда, 17 декабря 2008 г.

NAT из ad-hoc wi-fi в кабель

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

iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

ну и конечно

echo 1 > /proc/sys/net/ipv4/ip_forward

для включения собственно пересылки, а также

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

для закрепления результата.
На подключаемом устройстве естествено назначаем настроенную таким образом машину шлюзом по умолчанию.

понедельник, 1 декабря 2008 г.

SuSE, R40 и море удовольствия...

Что хочется сказать... Если вдруг по недоразумению судьбы у вас оказался ноут Sumsung R40(ну и, полагаю, любой другой с wi-fi на базе "Atheros Communications Inc. AR2413 802.11bg"), вы поставили на него OpenSuSE версии так 11(боюсь также и любой дистриб с использованем ath5k по умолчанию) не тратьте время на оживление беспроводной сети с помощью предустановленного драйвера. Вместо этого читайте это замечательное руководство, ставте с его помощью дровину от WinXP и наслаждайтесь жизнью. Да и не помешает перезагрузиться - похоже глючный драйвер не любит сдавать оккупированные позиции :)

среда, 22 октября 2008 г.

Ещё одна странность JBoss

Почемута JDBC драйвер для PostgreSQL выложенный в папку /lib приложения подцепляется неправильно. /*Сдаётся мне проблема в извращённом класслодинге и/или том хаке, который я описывал простом раньше*/ При обращении выдаёт ошибку в духе: "неправильный драйвер для такой строки соединения". Лечение тривиально - положить жарник с драйвером в /lib сервера.

Раздельные логи приложений в JBoss

Встала задача организовать раздельную запись логов для нескольких экземпляров одного и того-же приложения, запущенных на сервере(разделение экземпяров просто переименование war-ок). При этом дополнительно хотелось получить также: конфигурирование логов отдельно от самого сервера(читай не в серверном jboss-log4j.xml, а в собственном конфиге приложения, один экземпляр log4j как на диске, так и в памяти.

Простая упаковка конфига вместе с приложением успеха, как и ожидалось, не принесла. Если верить форумам/мэйллистам причина в том, что по умолчанию JBoss подкладывает приложениям свои библиотеки в класспат, соответственно приложения используют уже инициализированный экземпляр log4j.
Вторым этапом стала попытка использовать хак со слушателем контекста и установкой в нём RepositorySelector'а взятый тут, раздел 10.3.8(что примечательно попал он мне на глаза сначала в каком-то блоге, а не в оф. доке). Работал он плохо: при переразвёртываниии приложения падала ошибка при инициализации JBoss log4j plugin. Думаю из за того, что при этом старый ClassLoader убивается и все созданные им классы вместе с ним. Заниматься дебагом сервера было немного лень, а сообщение обошибке было, мягко говоря, кратким.
В третий заход применил подход описанный там-же в разделе 10.3.6. А именно: положил в папку WEB-INF/lib log4j и commons-logging(в своём приложении на всякий случай решил использовать его, а не напряму log4j), положил в папку WEB-INF/classes свой log4j.xml а также создал файлик jboss-web.xml(до этого обходился стандартным дескриптором) с содержимым, описанным в доке чуть ниже.
Потом ещё переучил оставшийся с прошлой попытки листенер записывать в системные свойства имена приложения(точнее контекста) и конфига(log4j.xml). /*В спринге есть специальный, более одарённый листенер для этих целей, но спринга пока в проекте нет и связываться было лень.*/
Commons-logging увидел старшого брата без дополнительных манипуляций.

Результат: аккуратненький набор папочек в /log сервера с подневными логами соответствующих приложений. Надо отметить, что это, между тем, не совсем нирвана ибо экземпляр log4j на каждое приложение - и память не по делу и место на диске... в эпоху гигабайтных планок не сильно проблемно, но всё-таки. Есть мнение, что если поглубже покопать в серверный класслоадинг
(точнее хоть чуть-чуть копнуть, ибо то, что вписал в конфигурашку я понял приближённо) можно её и достичь...