Subscribe

Categories

Checkio.ORG

Subscribe to Posts

Email:

  • 10Aug

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

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

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

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

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

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

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

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

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

    Итак начнем.

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

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

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

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

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

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

    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 08Aug

    КАк оказалось. И у меня, дюжену ценных коментов съел мой дорогой спам фильтр. Поэтому мы на ночь глядя прошлись по коментам, поченым как спам и подтверждали все которые не адулт или “вау у вас такой классный блог”.

    Теперь пользуйтесь пока рекапчей. Спасибо. А на коменты завтра с утра с новыми силами начну отвечать.

    Всем удачных выходных

    Rating 3.00 out of 5
    [?]
  • 07Aug

    Хоть и старенькое, но полезненькое.
    Основатель Pinax James Tauber. Рассказывает о своем детище. Pinax – это сборная солянка джанго апов для ускорения разработки. Апы в основном с уклоном на социальность. Вобщем упомянутые апы в любом случае стоят вашего внимания.

    PyCon 2009

    Rating 3.00 out of 5
    [?]

    Tags: , , , ,

  • 06Aug

    (копипаст, решил, что люди должны знать правду )

    meditation

    Rating 3.00 out of 5
    [?]
  • 06Aug

    Как один из сподвижников открытых технологий Mozilla опубликовала каталог популярных открытых тулсов для веб разработчиков. Лично у меня глаза разбираются. Что тут сказать пацаны молодцы. Правда их навороченная версия в виде облака логотипов — мною воспринималась с трудом, поэтому я сразу перешол к простому ХТМЛ каталогу в виде таблици.

    Возможно у них и с модерацией плохо, потому что встречаются и 404 и бесплатно только 30 дней демо. Но взгляд мой остановился на одной чудной диковине, надо заметить, что идея создания подобной штуки у меня уже давно зрела. Но то что сделали эти пацаны, я б такое поднял с трудом.

    Тестинг веб приложения по средствам веб браузеров. selenium. Т.е. после запуска теста — открывается веб браузер, и прогоняет все указанные вами тесты. Нажми там, ввиди в это поле то, нажми по этой кнопке, подожди пока загрузится страница. Проверь, чтоб там было написано это. КРУТЬ!

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

    Кроме того, вы такие же тесты можете написать на любимых вами языками. Python, DotNet, Java, PHP, Ruby, даже старичка Perl-а не забыли. Можете скачать всю коллекцию с примерами на официальном сайте. В архиве сразу идет Java сервер, через который все это и работает ( и конечно же слово сервер предпологает, что он должен быть предварительно запущен java -jar selenium-rver.jar ) .

    На питоне — можно написать просто юнит тест, который, к примеру открывает яндекс и вводит в поиске привет мир.

    1. from selenium import selenium
    2. import unittest
    3.  
    4. class TestGoogle(unittest.TestCase):
    5.     def setUp(self):
    6.         self.selenium = selenium("localhost", \
    7.             4444, "*firefox", "http://ya.ru")
    8.         self.selenium.start()
    9.        
    10.     def test_google(self):
    11.         sel = self.selenium
    12.         sel.open("http://ya.ru")
    13.         sel.type("//input[@name='text']", "hello world")
    14.         sel.click(u"//input[@value='Найти']")
    15.         sel.wait_for_page_to_load(5000)
    16.    
    17.     def tearDown(self):
    18.         self.selenium.stop()
    19.  
    20. if __name__ == "__main__":
    21.     unittest.main()

    Надо будет еще попробовать на виртуальной машине с виндой покрутить все остальные браузеры. Оно же поддерживает еще сафари с ие. Уверен, за этой штукой будущее в области тестирования веб приложений.

    Так что жизнь налаживается, не стоим на месте. Всем удачного дня.

    Rating 3.00 out of 5
    [?]
  • 05Aug
    1. import sys
    2. #from twisted.internet.interfaces import IAddress
    3. name = 'twisted.internet.interfaces.IAddress'
    4.  
    5.  
    6. def import_class(line):
    7.     line = line.split('.')
    8.     mname = '.'.join(line[:-1])
    9.     if mname in sys.modules:
    10.         mname = sys.modules[mname]
    11.     else:
    12.         __import__(mname)
    13.         mname = sys.modules[mname]
    14.     return getattr(mname,line[-1])
    15.  
    16.  
    17. print import_class(name)
    Rating 3.00 out of 5
    [?]

    Tags: ,

  • 04Aug

    kombainПоследнее время мучает одна идея. Мне как всегда кажется, что она реально не нова, и если это так, скажите мне, как это дело называется.

    Если помните, я уже писал о тестировании наследниками. Теперь у меня родилась идея организации инлайн тестов, также намного своеобразным способом.

    Что если проект разделить на 2, или создавать 2 его копии. Один будет для боевого сервера, а второй будет для сервера разработки. И проект для разработки будет отличатся от проекта для боевого только тем, что в него будут включены проверки входных данных для всех блоков программы ( или критичных, или точек взаимодействия модулей ), это бывает полезно, когда несколько человек работает на одним проекта и надо проверять, чтоб один разработки пользовался интерфейсом модуля другого разработчика правильно. Но все эти проверки не нужны на боевом, или не нужны с определенного времени. Т.е. чтоб от них можно было легко избавится и легко включить обратно.

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

    Задача решается на python.

    У python есть массив каталогов, в которых он ищет модуль, как только вы хотите его импортировать. И этот список каталогов можно расширять во время работы программы.

    1. import sys
    2. sys.path.apend('/home/oduvan/list_of_my_cool_modules')

    Python позволяет один и тот же модуль импортировать с разными именами. Т.е. в области видимости, в которую мы импортируем модуль — мы можем дать ему несколько различных имен.

    1. import sys
    2. import sys as new_sys

    И можно все имена из одного модуля импортировать в другой модуль.

    1. from sys import *

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

    Решение.

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

    Ниже приведена структура каталогов и файлов нашего проекта.

    modules
    	__init__.py
    	develop
    		__init__.py
    		t1.py
    	production
    		__init__.py
    		t1.py
    		t2.py
    run.py
    

    В modules/production собраны все модули для боевого сервера
    В modules/develop модули с проверками данных
    run.py скрипт, в котором они будут использоваться.

    Замете, что в папке modules тоже есть файл __init__.py, т.е. он также будет точкой отсчета для импорта.

    В папке develop есть файл t1.py для тестирования такого же модуля из продакшена, или его части. А также мы видим, что модуль t2 остается без тестов.

    ( Автор просит прощения, за такие без звучные имена, с фантазией у него совсем все плохо )

    Приведу пример модуля t1 из production

    1. def p_name():
    2.     print 'Production'
    3.    
    4. def just_in_prod():
    5.     print 'This just in prod'
    6.  
    7. def sum2(a,b):
    8.     return a+b
    9.    
    10. class A(object):
    11.     def b_prop(self,b):
    12.         return b.prop
    13.  
    14. class B(object):
    15.     def __init__(self,prop):
    16.         self.prop = prop

    функция p_name просто нужна для вывода имени модуля или репозитария, для нас она особой ценности не имеет.
    just_in_prod — тестироваться этой функции проводится не будет
    sum2 — складывает 2 числа. И мы хотим проверить, чтоб это на самом деле были 2 числа.
    Объект класс A имеет метод, который на вход получает один параметр — объект класса B, и возвращает его свойство. Класс B мы также тестировать не будем.

    Как сами уже можете видеть, в модуле нет ни одного слово о тестах. Вы видите чистый функционал.

    Теперь приведу вам пример модуля t1 из develop

    1. from production.t1 import *
    2. import production.t1 as P
    3. def p_name():
    4.     print 'Develop'
    5.     P.p_name()
    6.  
    7. def sum2(a,b):
    8.     if not isinstance(a, (int,float)):
    9.         raise ValueError('a must be int or float')
    10.     if not isinstance(b, (int,float)):
    11.         raise ValueError('a must be int or float')
    12.     return P.sum2(a,b)
    13.    
    14.    
    15. class A(P.A):
    16.     def b_prop(self,b,*args,**kwargs):
    17.         if not isinstance(b, B):
    18.             raise ValueError('first argument must be instance of B')
    19.         return super(A,self).b_prop(b,*args,**kwargs)

    Первые 2 строчки всегда должны быть в модуле тестирования.

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

    Проверка для функции sum2 и проверка для свойства b_prop из класса A.

    Ну и текст скрипта, который демонстрирует процесс работы и тестирования run.py. Предполагается, что у вас это и будет точкой отсчета для запуска.

    1. import sys
    2. sys.path.append('modules/develop')
    3. sys.path.append('modules')
    4. sys.path.append('modules/production')
    5.  
    6. import t1,t2
    7. t1.p_name()
    8. print '—'
    9. t1.just_in_prod()
    10. t2.in_only_production()
    11. print '—'
    12. o_a = t1.A()
    13. o_b = t1.B('it_s prop')
    14. print o_a.b_prop(o_b)
    15.  
    16. print t1.sum2(1,2)
    17.  
    18. print o_a.b_prop(15)

    В этом скрипте важным является порядок добавления модулей в массив sys.path, ну и то, чтоб эти строчки были самые первые в вашем скрипте.

    Вывод скрипта будет следующий

    Develop
    Production
    ---
    This just in prod
    Only in production
    ---
    it_s prop
    3
    Traceback (most recent call last):
      File "run.py", line 18, in 
        print o_a.b_prop(15)
      File "modules/develop/t1.py", line 18, in b_prop
        raise ValueError('first argument must be instance of B')
    ValueError: first argument must be instance of B
    

    для боевого сервера он будет такой же, только в «шапке» скрипта будет не

    1. import sys
    2. sys.path.append('modules/develop')
    3. sys.path.append('modules')
    4. sys.path.append('modules/production')

    а

    1. import sys
    2. sys.path.append('modules/production')

    В этом случае поменяется только текст ошибки

    Production
    ---
    This just in prod
    Only in production
    ---
    it_s prop
    3
    Traceback (most recent call last):
      File "run.py", line 18, in 
        print o_a.b_prop(15)
      File "modules/production/t1.py", line 12, in b_prop
        return b.prop
    AttributeError: 'int' object has no attribute 'prop'
    

    Я думаю люди, которые часами разбирались в мало понятных ошибках модулей — оценят идею.

    Да, и еще одним плюсом является то, что вы можете делать легко несколько профилей тестирования и легко между ними переключатся, Добавив рядом с папкой develop, что нить типа develop_plusplus, или если вы хотите залить на продакшн тесты, но не хотите тестировать все, а только те чатити, которые подвержены изменения develop_light.

    Я же планирую у себя это использовать для своего сокет сервера. У меня именно так разнесен скрипт run.pay от функциональных модулей. И думаю при запуске его добавить еще параметр -t которому можно будет передать имя профиля тестирования.

    Файлы из примера split_develop.tar

    Вот и все. Жду жесткую критику, предложения по улучшению.

    Спасибо, что дочитали до конца :)

    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 01Aug

    Lazy Crazy Coder’s blog from Alexander Artemenko.

    Для себя отметил пару ссылок оттуда.

    Python testing tools

    Big list of Django tips (and some python tips too) – статья не новая, но есть еще очень актуальные вещи.

    Rating 3.00 out of 5
    [?]

    Tags: , , , ,

  • 01Aug

    с утра зашел проверить утренние филы. И вот наткнулся celery. Теперь тяжеловесные задачи на откладывать на потом. И делается это очень просто, по крайне мене судя по документации. Тут более подроная апишка.

    Оставил себе таск на выходные порытся и тут. Обо всем напишу тут.

    PS: первое, к чему бы я сразу это прикрутил – это отсылка мыла. Ее всегда полезно отложить :)

    Всем удачных выходных.

    Rating 3.00 out of 5
    [?]

    Tags: , , , , , , ,

   

Recent Posts

Recent Comments

  • Почему-то признаки такой "застенчивости" в рунете преобладаю...
  • >и пишеш стать>пишешОбманчивая самоуверенность...
  • Установщик макоси не видит жёсткий диск :(...
  • Когда будет 2я часть статьи? Хотелось бы почитать!...
  • Голоса пользователей. Питон красивый язык, а красоту может о...