Почему стоит понижать кульутру производства


The Presentation inside:

Slide 0

Почему стоит понижать кульутру производства На что обращать внимание, создавая приложения для Django Дмитрий Лебедев http://course.ryba4.com skype: siberianoNsk +7 923 732 1337


Slide 1

2 Культура производства “Программист должен не забыть. Пусть будет высокая культура производства.”


Slide 2

3 Культура производства совокупность нормативных требований к технико-экономическому, организационному и эстетическому уровню производства.


Slide 3

4


Slide 4

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


Slide 5

6 Примеры завышенной культуры производства Что должно быть синхронным, лежит далеко Слово “прописывать” Огромное количество настроек, которые надо запомнить Сложные протоколы


Slide 6

7 Пример №1. Документация Ещё один пример данных, которые должны быть синхронными. Код – Документация


Slide 7

8 Пример №1. Документация Недостатки документации в Wiki Неохота исправлять Неточности незаметны Размыта ответственность Не интегрируется с IDE или консолью


Slide 8

9 Docstrings In [65]: zip? Type: builtin_function_or_method Base Class: <type 'builtin_function_or_method'> String Form:<built-in function zip> Namespace: Python builtin Docstring: zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)] Return a list of tuples, where each tuple contains the i-th element from each of the argument sequences. The returned list is truncated in length to the length of the shortest argument sequence.


Slide 9

10 Docstrings Вместе с кодом Исправить — дело нескольких секунд Неточности заметны сразу Ответственность — на авторе, проверяется на обзоре кода Легко получить документацию из консоли или IDE Сделать документацию в виде HTML можно при помощи инструментов В Wiki храним то, что никуда не пристраивается


Slide 10

11 Антипример №1, Debug Toolbar INSTALLED_APPS = ( ... 'debug_toolbar',


Slide 11

12 Антипример №1, Debug Toolbar MIDDLEWARE_CLASSES = ( ... 'debug_toolbar.middleware.DebugToolbarMiddleware', ... )


Slide 12

13 Антипример №1, Debug Toolbar INTERNAL_IPS = ('127.0.0.1',)


Slide 13

14 Сборка проекта $ hg clone ssh://bitbucket.org/siberiano/course.ryba4.com course $ cd course $ make run ... Development server is running at http://0.0.0.0:8001/ Quit the server with CONTROL-C. ... $ make rebuild Rebuilding the database...


Slide 14

15 Большая инструкция приводит к ошибкам Обновившиеся зависимости — это отрезанные пальцы Сборка проекта


Slide 15

16 Нужен инструмент сборки, чтобы собрать зависимости проекта на новом месте развернуть базу данных пересоздать базу данных зафиксировать версии зависимостей Существующие решения: django-fab-deploy fastdev-django самодельное решение на virtualenv или bootstrap.py Сборка проекта


Slide 16

17 Файлы fixtures нужно пложить по таким путям: apps/polls/dev_fixtures/initial_data.json apps/messages/dev_fixtures/initial_data.json В настройках приходится указать FIXTURE_DIRS = ( 'apps/polls/dev_fixtures/', 'apps/messages/dev_fixtures/', ) Пример №2, fixtures


Slide 17

18 Пути этих файлов строгие и уже содержат всю необходимую информацию, чтобы их найти. Решение проблемы: FIXTURES_DIRS = tuple(ln.rtrim() for ln in os.popen('find . -path "*apps*dev_fixtures"')) Пример №2, fixtures


Slide 18

19 Пример №3, спрайты .folder.opened { width: 16px; height: 16px; background-image: url("icons.gif"); background-position: -64px -16px; }


Slide 19

20 Пример №3, спрайты Настройки для приложения, делающего спрайты: sprite=Sprite.create_from_local_files(['/path/to/first/file', '/path/to/second/file'])


Slide 20

21 Пример №3, спрайты # settings.py SPRITES_DIR = 'static/img/sprites' sprites/ sprite_one/ icon1.png icon2.png sprite_two/ icon3.png icon4.png


Slide 21

22 Пример №4, urls и javascript Статический файл js: $.ajax({url: '/path/to/API/', …}) Urls.py: url(r'^api/$', api_view, name='api') Связка разваливается, когда изменяют одну из этих 2 строк.


Slide 22

23 Пример №4, urls и javascript Функция в JS: reverse_url = function(url_name, params){ params = params || {}; $.extend(params, {url_name: url_name}) return '/reverse_url/?' + $.param(params); };


Slide 23

24 Пример №4, urls и javascript Middleware: class UrlReverseMiddleware(object): def process_request(self, request): if request.path_info == '/reverse_url/': query_dict = request.GET.copy() url_name = query_dict.pop('url_name')[0] args = query_dict.pop('args', []) if args == ['']: args = []


Slide 24

25 Пример №4, urls и javascript try: request.path = request.path_info = reverse(url_name, args=args) except NoReverseMatch: raise Http404 request.GET = QueryDict(query_dict.urlencode())


Slide 25

26 Пример №4, urls и javascript Использование: reverse_url('complicated_url', {args: [1, 2], param1: 3}); /reverse_url/?url_name=complicated_url&args=[1, 2]&param1=3 Преимущества: Адрес можно перемещать Можно искать использование адреса по его имени


Slide 26

27 Пример №5, протоколы Так можно: def view1(request, arg1, arg2): pass def view2(request, arg1, arg2): pass


Slide 27

28 Такого стоит избегать: data ={ 'location': place.name, 'date': visit.date, 'event': 'visit', 'type_of_' + place.__class__.__name__: place.place_type, } Пример №5, протоколы


Slide 28

29 Изменения всегда нужно делать в паре Не отлаживается статическим анализатором Не отлаживается дебаггером


Slide 29

30 Было переписано так: data = { 'event': visit, # объект класса Event } # visit.place — место # visit.user — человек


Slide 30

31 Пример №6, меню приложений Много файлов apps/app/menu.html Много файлов templates/app/url.py


Slide 31

32 <div class="submenu"> <a href="{% url photos %}">Фотоальбом</a> <a href="{% url calendar %}">Календарь</a> {% if request.user.is_authenticated() %} <a href="{% url inbox %}">Входящие сообщения {% if request.user.new_msg %} <b>({{ request.user.new_msg }} новых)</b> {% endif %} </a> {% endif %} {% if request.user.is_authenticated() %} <a href="{% url create_request %}"> Подать заявку</a> {% endif %} </div>


Slide 32

33 Сложная вёрстка повторяется в шаблонах меню


Slide 33

34 urlpatterns = patterns('views', item(url(r'^photos$', 'photos', name='sport_photos'), caption='Фотографии'), item(url(r'^calendar$', 'calendar', name='sport_calendar'), caption='Календарь'), item(url(r'^inbox$', 'inbox', name='sport_inbox'), caption='Входящие', template= 'sport/menu_inbox.html'), item(url(r'^request$', 'create', name='sport_create_request'), caption='Подать заявку'), url(r'^ajax_request$', 'ajax', name='sport_ajax'), )


Slide 34

35 <div class="submenu"> {% for item in submenu %} {# права уже проверены #} {{ item }} {% endfor %} </div>


Slide 35

36 Пример №6, меню приложений, итоги


Slide 36

37 Как можно делать новое приложение Проверить, нет ли готовых решений Определить кто им пользуется из разработчиков как ему удобнее им пользоваться какие данные (шаблоны, статические файлы, адреса) потребуются Поместить минимальный набор данных на нужные места Написать приложение под эти данные


Slide 37

38 Резюме. Принципы. Не делайте ненужных настроек Настройки должны быть там, где ими пользуются Документация — в коде Проект должен собираться автоматически


×

HTML:





Ссылка: