Рефакторинг

15.10.2010

Расскажу про свой опыт рефакторинга на примере эволюции PHP-функций чтения/записи для Daos.

  1. Сперва данные (в массиве) просто подвергались [де]сериализации и записывались/читались без всяких проверок. Выяснилось, что стоит попасть в данные одинарной кавычке, как всё рушится.
  2. Переписал на JSON, но это было совсем недолго. Оказывается, современные версии PHP далеко не у всех хостеров установлены. Кроме того, сериализация в JSON коряво работала для русских символов, они преобразовывались в абракадабру. В топку.
  3. Осенило! Почему бы не использовать var_export? Это очень удобно, и такой способ даёт возможность легко просматривать и редактировать файлы с данными. Замечательно. Замедление в сравнении с JSON и сериализацией если и есть, то ничтожное.
    Однако, всё ещё не было никаких проверок на одновременный доступ. Я почему-то был уверен, что PHP де-факто исключает такие ситуации, контролирует их. Я ошибся. Но это не камень в огород PHP, я считаю, что он и не должен их отслеживать.
  4. Узнаю про flock и делаю версию с блокировками. Вот теперь в огород PHP полетят камни. Увы, но flock на самом деле не гарантировал ничего…
  5. Особенно если его неправильно использовать :) Но переделанная функция всё равно допускала сбросы.
  6. Вместо flock я стал использовать переименование файла для записи и дополнительно записывал бэкапы. Почему-то без проверки целостности. Недостатки такого подхода: а) сбросы всё равно были! б) невозможно точно посчитать статистику при большой нагрузке.
  7. И вот теперь тестирую уже седьмой вариант, получается. Переписал всё с нуля, сейчас для чтения и записи проверяется маленький блокировочный файлик. Новые функции пока что показали себя с наилучшей стороны, ночное стресс-тестирование завершилось нулевым количеством сбросов. Предыдущий вариант при аналогичных условиях сбрасывал данные 25 раз.

Такие дела. Я теперь понимаю, почему в книге «Совершенный код»1 Стив Макконнелл рекомендует проектировать методы несколько раз вообще всегда. Потому что очень редко с первого раза учитываешь все варианты. Хотя, конечно, ценность этой рекомендации сильно зависит от опыта программиста — очевидно простые функции можно писать сразу.

Я за последние несколько дней набрал месячную норму багажа знаний, причём не только в программировании, я теперь лучше понимаю UNIX, что вообще кайфово, настоящее удовольствие получаю от этого. А за последние два месяца знаний прибавилось, пожалуй, больше, чем за год ранее. Классно.

В следующей заметке я расскажу о тестировании различных вариантов функций чтения/записи. С цифрами, таблицами, может даже картинками :) Кроме меня этой задачей заинтересовались ещё несколько человек, спасибо им большое. В исследовании будут рассматриваться четыре варианта реализации:

Уже появилось продолжение. Пишите отзывы!

1 Читайте мой отзыв о книге «Совершенный код».

Комментарии

  1. # aktuba

    Все-таки ты Тормоз =))). Ну кто для финансовой системы во главу ставит удобство установки, а не надежность??? Используй уже хоть какую-то базу»

  2. # Миша: 

    про кавычку совсем не понял
    про json тем более
    раз они «преобразовуются» значит так нужно, ты не находишь?

  3. # Тормоз

    Это не финансовая система. И я уже с файлами пришёл к достаточно совершенному решению, на кой чёрт здесь база? + Уже раз 20 говорил, что в этом коде уже не буду переделывать всё, это просто глупо. В Daos 2.0, возможно, будет БД, здесь — нет. И точка.

    Миша, ссылки же есть. Почитай. Не нахожу, что так нужно в UTF-8.

  4. # IAD

    Надеюсь маленький блокировочный файлик со случайным содержимым известным только создавшей его функции?

  5. # IAD

    Да, и неплохо бы писать в отдельный файл лог заказов, просто через >>. На случай восстановления из крэша

  6. # Бутылк.Ус

    К чёрту базы! Продолжаем в том же духе =)

    Тормоз, есть еще такая конструкция в пыхе: declare() и к ней register_shutdown_function() (не уверен в точности написания последней, пробовал только в процессе обучения, уже не помню, погугли).
    Короче алгоритм оставляем такой же, но после выполнения скрипта запустится неявно вызываемая функция, которая с нормальным принудительным flock сверит бекап и обновление. Если где найдется косяк – восстановит и перепроверит. Это уже что называется «забетонировать» дыру.

    ЗЫ: Насчёт регулярок ты неправ. Отпишусь к твоему комменту у меня чуть позже.

  7. # Бутылк.Ус

    Йопрст…
    Только сейчас «грепнул по сорцам»…
    А почему ты не используешь flush()??? Это же как раз нужное тебе – принудительный сброс буфера записи на диск до всяких анлоков и фклоузов =)

  8. # polonskiy: 

    Привет. Вот еще по поводу блокировки файлов:
    1. forum.dklab.ru/viewt…
    2. forum.dklab.ru/viewt…
    3. www.forum.dklab.ru/v…
    4. cubicspot.blogspot.c…

  9. # Миша: 

    пока ваш зенд будет парсить параметры по паттерну из строки, другой скрипт заблокирует файл
    от записи и перезаписи с каждым реквестом, винчестер очень быстро скажет вам спасибо, попомните мое слово

  10. # Бутылк.Ус

    Миша, то верно подмечено. Только вот «спасибо» будет говориться хостинг-провайдеру, поэтому особо опасаться нечему.
    Хотя, база данных это те же кучки файлов, при записи в базу точно также перезаписываемые. Так что пофиг в принципе.

  11. # Тормоз

    Надеюсь маленький блокировочный файлик со случайным содержимым известным только создавшей его функции?

    Зачем блокировочному файлу содержимое вообще?

    …есть еще такая конструкция в пыхе: declare()

    Она тут не к месту совсем. Но declare я использовал для оптимизации, удобно отслеживать время выполнения отдельных частей скрипта. И flush() тоже совсем для других целей предназначен.

    P.S. Сегодня ночью оставлял на тест вариант с сессиями, предложенный асоциальным программистом, правда, сделал его по-своему. И вот эта штука показала себя весьма неплохо. Так что рефакторинг продолжается :)

  12. # Миша: 

    содержимое для проверки, но в твоем случае оно реально никчему
    @Бутылкус еще как есть чему, думаешь долго провайдер будет такой скрипт у себя терпеть?
    база данных это далеко не просто кучи файлов, начнем с того что это один файл, в основном, и закончим тем что работа с ним абсолютно по другому организованна
    я надеюсь, по крайней мере :)
    в современных так уж точно

  13. # Тормоз

    Ну тут уж смотря какой хостер, наверно. У них разве нет каких-нибудь кэшиков прямо в оперативной памяти? У меня в /tmp tmpFS, я пробовал туда Daos ставить — работает.

  14. # Миша: 

    Много ли людей его в tmpfs поставят, как думаешь? Если они настолько тупы что субд настроить не могут (из твоих же соображений)?

  15. #  Тормоз

    Ты нифига не понял. Я имел в виду, что нельзя быть увереным на 100%, что хостер не оберегает свои диски с помощью каких-либо технологий. В конце-концов это именно его диски и его проблемы.

Комментирование этой статьи закрыто.

Интересное Покупки ТехникаРазное Отдых Статьи Строительство Услуги Общество Хобби Культура Советы Уют