• 10Aug

    tolsti_i_tonkiРефакторинг – процесс полного или частичного преобразования внутренней структуры программы при сохранении её внешнего поведения.

    У кого, когда возникает мысль, о том, что пора бы переписать эту часть программы ( этот класс, эту функцию )?

    У меня, это начинается после пятого костыля. Костыль — это добавления не предусмотренной функциональности к объекту. Не предусмотренной изначальной архитектурой либо заложенной расширяемости в ней. О как закрутил. Если просто, то пример. Есть пользователь, к которого есть свойство «группа», возвращающее стринговое имя группы, в которую он входит, через некоторое время оказывается, что пользователь может входить в несколько групп и вы пока ставите костыль, но часть функционала по работе с группами надо будет потом переписать. И как я части видел — «костыльная» практика очень свойственно для изначально не формализованных проектов, когда заказчик точно еще понимает, что он хочет ( или пока не может это ясно выразить, а вы его ясно понять ).

    Делать полный рефакторинг после первого костыля, в таких проектах, дело очень расточительное. Но пометку о том, что в этом месте «костыль» – надо поставить. Добавьте функциональный тест на этот костыль. Когда обилие костылей — мешает вам жить, и перед добавлением нового функционала вы выпиваете корвалола. То пора. Пора делать инспектировать и рефакторить код.

    Но, как мне кажется, каждый программист — после первого месяца серьезного программирования уже знает, что такое рефакторинг. Возможно слово такого еще не знает, но точно знает, что ему это уже хочется.

    Рефакторинг кода может быть связан не только с изначальной архитектурной убогостью. Его проводят после понимания того что «что то у нас все очень тупит» ( хотя тут слово «оптимизация» подходит больше ). В этом случае проводится рефакторинг узкого места программы. Профилировка поможет его определить. Бывает это помогут вам определить и пользователи, просто говоря, в каком месте у них «долго думает». Был свидетелем того, как узкое место программы определяли на глаз. Более того, код которым заменяли «тупящий» – не факт, что работал быстрее. Проверяйте!!! Бенчмарк как и профилировка есть в любом языке программирования. Но это отдельная тема, которую сейчас я обсуждать не буду.

    И самая страшная причина, по которой могут проводить рефакторинг. Начинается примерно с таких слов. «Я тут прочитал одну статью на форуме, так вот там сказали, что лучше юзать вот эту штуку вместо этой. И на сайте у них говорится, что у них все круто и круче них только Чак Норис. Давайте переезжать!». В топку! Холивары оставляем на форумах. Безусловно, когда вы увидите, что место у вас и правда узкое, то эти знания будут вам крайне полезны. Но просто так оптимизировать все подряд — глупо и дорого. Возможно это даже не будет ваше самое узкое место.

    Да. Затянутое получилось введение.

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

    Итак начнем.

    1.Если ваш проект уже запущен у него есть аудитория, то без железобетонного набора тестов пускаться в удивительный мир рефакторинга я крайнее не советую. Если тестов нет, то с начало напишите их.
    2.Пройдитесь по коду (если есть возможность используйте дебаг) с каждой точки входа в программу до точки выхода. И простым языком описываем процедуру взаимодействия с объектом на отдельном листке. Можно также помечать какие свойства или методы связаны с описываемыми действиями — это может быть полезно в выявлении дублирующего кода. Как правило уже в процессе письма я вижу места, программы, которые либо выполняют ненужные телодвижения, дублируют друг друга. Выписываем их на отдельный листок. Вообще я считаю, что даже программисту иногда полезно взять ручку и листочек в руки, хоть сейчас просто море программ и сервисов, которые с легкостью из заменяют.
    3.После того, как вы опишите все это. Словесные описания можно сгруппировать в блоки. Вы сразу видите ( как бы сверху ) на поведение своего объекта, точки соприкосновения с другими объектами. Получается такой процесс, обратный проектирования. Если при проектировании я описания задачи свожу к написанию кода, то тут я код свожу к описанию задачи, которую он выполняет. И выражаю эти блоки уже кодом программы.
    4.Изменяя функцию, я не комментирую ее (полностью или частями) я просто добавляю к ней приставку __OLD и пишу новую без этой приставки это касается и свойств. Если функция переносится в другой объект, то я на против __OLD оставляю комментарий с описанием, куда она была перенесена.
    5.Приставка __OLD также полезна в случае, если вы, в процессе описания, увидили дублирующие функции или свойства. Или почти дублирующие. Одну из функций-близнецов переименовываем и прогоняем тесты. В местах ошибок заменяем на правильную.
    6.После проведенной предварительно описательной работы — написание кода у вас займет в разу меньше времени.
    7.Оставшуюся описательную макулатуру после рефакторинга переведите в документацию.

    Да, и самое главное. На дело лучше идти с утра, когда голова еще светла.

    У меня после описательной работы и кодирования наверно штук 20 функций были искалечены словами OLD, и над ними красовались 3-4 которые теперь были вместо них.

    И помните. Книга считается законченной не тогда, когда нечего больше добавить, а когда нечего больше выкинуть.

    Вот такой опыт. А как проводите это вы? Есть ли у вас какие-то обязательные предварительные условия? Возможно какие-то правила рефакторинга, которые вы используете? Было бы очень интересно услышать еще одно мнение.

    Спасибо за внимание и удачного для.

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 15Jan

    Итак, подборка советов из newcontimemt.ru:

    * Используйте постоянные подключения к базе данных, чтобы избежать накладных расходов на текущие подключения. Если Вы не можете использовать постоянные подключения, и Вы делаете много новых подключений, стоит изменить значение переменной thread_cache_size
    * Обязательно проверьте, что все Ваши запросы в самом деле используют индексы, которые Вы создали в таблицах. В MySQL Вы можете сделать это командой EXPLAIN.
    * Избегайте сложных запросов SELECT на таблицах, которые часто модифицируются. Это должно помочь избежать проблем с блокировкой таблицы.
    * Новые таблицы MyISAM могут вставлять строки в таблицу без удаленных строк в то же самое время, когда другой запрос ведет чтение. Если это важно для Вас, Вы должны рассмотреть методы, где Вы не должны удалить строки или выполните OPTIMIZE TABLE после того, как Вы удалили много строк сразу.
    * Используйте вызов ALTER TABLE … ORDER BY expr1,expr2… если Вы обычно получаете строки в порядке expr1,expr2,… . Используя эту опцию после внесения больших изменений для таблицы, Вы можете получить значительно более высокую эффективность.
    * В некоторых случаях может иметь смысл представлять столбец, который является хэшем, основанным на информации из других столбцов. Если этот столбец короткий и приемлемо уникальный, это может быть намного быстрее, чем большой индекс на многих столбцах. В MySQL это очень легко в использовании: SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND col_1=’constant’ AND col_2=’constant’
    * Для таблиц, которые часто изменяются, Вы должен пробовать избежать любых столбцов типов VARCHAR или BLOB. Вы получите динамическую длину строки, как только Вы используете хоть один стобец VARCHAR или BLOB.
    * Если Вы очень часто должны вычислять значения, основанные на информации из большого количества строк (подобно количеству), вероятно, намного лучше представить новую таблицу и модифицировать счетчик в реальном времени. Модификация типа UPDATE table set count=count+1 where index_column=constant очень быстрая! Это действительно важно, когда Вы используете базы данных подобные MySQL, которые имеют только блокировку уровня таблицы. Это также даст лучшую эффективность с большинством баз данных, поскольку администратор блокировки строки в этом случае будет иметь куда меньше работы.
    * Если Вы должны собрать статистику из больших таблиц файла регистрации, используйте итоговые таблицы вместо того, чтобы просмотреть целую таблицу. Поддержание резюме должно быть намного быстрее, чем попытка сделать живую статистику. Намного быстрее получить новые итоговые таблицы из файлов регистрации, когда происходит изменение, чем менять работающее приложение!
    * Если возможно, нужно классифицировать отчеты как “живые” или “статистические”, где данные, необходимые для статистических отчетов, сгенерированы только, исходя из итоговых таблиц, которые в свою очередь были сгенерированы из фактических данных.
    * Воспользуйтесь преимуществом того факта, что столбцы имеют значения по умолчанию. Вставляйте значения явно только, когда значение, которое будет вставлено, отличается от значения по умолчанию. Это уменьшает синтаксический анализ, который MySQL должен сделать, и улучшает быстродействие вставки.
    * В некоторых случаях удобно упаковывать и сохранить данные в blob. В этом случае Вы должны добавить некоторый дополнительный код к Вашей прикладной программе, чтобы упаковать/распаковать данные, но это может сохранить много времени доступа в некоторой стадии. Это удобно, когда Вы имеете данные, которые явно не соответствуют статической структуре таблицы.
    * Обычно Вы должны пробовать хранить все данные неизбыточными (что названо третьей нормальной формой в теории базы данных), но Вы не должны бояться дублирования или создания таблиц-резюме, если Вы нуждаетесь в них, чтобы получить большее быстродействие.
    * Сохраненные процедуры или UDF (определяемой пользователем функции) может быть хорошим способом получить большую эффективность. В этом случае Вы должны, однако, всегда иметь способ делать это некоторым другим (более медленным) путем, если Вы используете СУБД, которая не поддерживает это.
    * Вы можете всегда получать неплохие результаты, кэшируя запросы/ответы в Вашей прикладной программе и пробуя делать много вставок/модификаций в то же самое время. Если Ваша база данных поддерживает блокировки таблиц (подобно MySQL и Oracle), это должно помочь гарантировать, что индексный кэш сбрасывается только однажды после выполнения всех модификаций.
    * Используйте INSERT /*! DELAYED */, если Вы не должны знать, когда Ваши данные будут записаны. Это ускоряет дела потому, что много записей могут быть выполнены за один дисковый обмен.
    * Используйте INSERT /*! LOW_PRIORITY */, когда Вы хотите, чтобы Ваши вызовы select были более важными.
    * Используйте SELECT /*! HIGH_PRIORITY */, чтобы получить select, обходящий очередь. То есть select будет выполнен, даже если имеется кто-то ждущий, чтобы сделать запись в таблицу.
    * Используйте многострочную инструкцию INSERT, чтобы сохранить много строк одной командой SQL (многие серверы SQL поддерживают это).
    * Используйте LOAD DATA INFILE, чтобы загрузить большие количества данных. Это быстрее, чем нормальные вставки, а будет еще быстрее, когда myisamchk интегрирован в mysqld.
    * Используйте столбцы с поддержкой AUTO_INCREMENT, чтобы сделать уникальные значения.
    * Используйте OPTIMIZE TABLE время от времени, чтобы избежать фрагментации при использовании динамического формата таблицы.
    * При использовании нормальной установки Web-сервера, изображения должны быть сохранены как файлы. То есть сохраните только ссылку на файл в базе данных. Основная причина для этого в том, что нормальный Web-сервер намного лучше при кэшировании файлов, чем содержание базы данных. Так что намного проще получить быструю систему, если Вы используете файлы.
    * Используйте таблицы в памяти для некритических данных, к которым обращаются часто (подобно информации относительно последнего показанного баннера для пользователей, которые не имеют cookie).
    * Столбцы с идентичной информацией в различных таблицах должны быть объявлены идентично и иметь одинаковые имена. До Version 3.23 Вы получали медленные объединения в противном случае. Старайтесь делать имена проще (например, name вместо customer_name в таблице заказчиков). Чтобы сделать Ваши имена переносными на другие SQL-серверы, Вы должны озаботиться тем, чтобы они не превышали в длину 18 символов.
    * Объявление таблицы с DELAY_KEY_WRITE=1 будет делать модифицирование индексов быстрее, поскольку они не регистрируются на диске, пока файл не закрыт. Обратная сторона в том, что Вы должны выполнить myisamchk на этих таблицах прежде, чем Вы запускаете mysqld, чтобы гарантировать, что они правильные, если что-то уничтожило mysqld в середине запроса. Поскольку информация ключа может всегда генерироваться из данных, Вы не должны терять что-нибудь, используя DELAY_KEY_WRITE.

    Использовался материал:

    1) newcontinent.ru

    2) dev.mysql.com

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

   

Recent Posts

Recent Comments

  • Я просто оставлю это тут: ...
  • спасибо...
  • Если вдуматься в каждое слово, то время беСконечно в русском...
  • Спасибо, Евгений, исправленно.P.S.: перехал на диску...
  • за опечатку - спасибо...