Опубликовано

20 вещей, которые я узнал за 20 лет работы инженером-программистом

Наткнулся на просторах сети на один материал от разработчика, который проработал в индустрии 20 лет. Я работаю больше 10 лет и соглашусь с каждым пунктом. Оригинальная статья

Дисклеймер от автора оригинальной статьи

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

«Вам просто нужно повысить цены» — говорит компания, которая 20 лет работала в бизнесе, выставляя поначалу низкие цены для привлечения клиентов.

«Вам нужно внедрять микросервисы» — говорит компания, которая построила монолит, набрала тысячи клиентов и перешла на микросервисы, когда столкнулась с проблемами масштабирования.

Без понимания контекста советы бессмысленны или, что ещё хуже, вредны. Если бы эти компании последовали собственным рекомендациям в начале пути, они, скорее всего, навредили бы сами себе.

Для понимания контекста расскажу, откуда берутся советы в этой статье. Первую половину карьеры я работал инженером-программистом в небольших компаниях и стартапах, потом перешёл в консалтинг и работал в нескольких действительно крупных компаниях. Затем основал Simple Thread, которая выросла из команды 2 человек до 25. 10 лет назад мы работали в основном с малым и средним бизнесом, сейчас — со средним и большим.

Советы в этой статье от человека, который:

  • почти всегда работал в небольших командах, где приходится делать много, имея очень мало;
  • ценит работающие решения выше конкретных инструментов;
  • постоянно начинает новые проекты, но поддерживает ряд систем;
  • ценит производительность инженера выше большинства других критериев.

Мой опыт за последние 20 лет сформировал отношение к разработке и убедил меня в некоторых утверждениях, которые я оформил в виде списка. Надеюсь, он вам будет полезен.

1. Я все ещё многого не знаю

«Как ты можешь не знать, что такое BGP?» или «Ты никогда не слышал о Rust?» — некоторые из нас не раз слышали подобное. 

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

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

2. Самое сложное в разработке — сделать продукт, который действительно нужен 

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

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

Инвестиции в процесс проектирования (с помощью UX-специалистов или путём самообразования) принесут огромные дивиденды. Ведь как реально подсчитать стоимость разработки неправильного ПО? Это гораздо больше, чем просто потерянное время инженера.

3. Лучшие инженеры-программисты думают как дизайнеры

Великие инженеры-программисты глубоко задумываются о пользовательском опыте. Они могут не думать об этом в терминах вроде внешнего или программного API, UI, протокола или любого другого интерфейса. Великие инженеры думают о том, кто будет его использовать, почему он будет использоваться, как он будет использоваться и что важно для пользователей. Учет потребностей конечного потребителя — это залог хорошего пользовательского опыта.

4. Лучший код — это отсутствие кода или код, который не нужно поддерживать

Всё, что нужно сказать: кодеры будут кодить. Если спросить человека любой профессии, как решить ту или иную проблему, он выберет то, что у него хорошо получается. Это просто человеческая природа. Большинство инженеров-программистов всегда будут склоняться к написанию кода, особенно когда нетехническое решение не очевидно. 

То же самое относится к коду, который не нужно поддерживать. Инженерные команды часто хотят изобрести колесо, когда оно уже существует. Здесь нужно соблюдать баланс, есть много причин для развития собственных разработок, но остерегайтесь токсичного синдрома «изобретено не здесь».

5. Программное обеспечение — это средство достижения цели

Основная работа любого инженера-программиста — предоставление ценности. Немногие разработчики понимают это, еще меньше тех, кто это осознает. А ведь осознание приводит к другому способу решения проблем и другому взгляду на инструменты.

Если вы действительно верите, что выбор ПО зависит от цели, то будьте готовы найти «правильный инструмент для работы», который может и не являться софтом.

6. Иногда нужно перестать точить пилу и просто начать пилить

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

7. Если у вас нет представления о границах возможного, вы не сможете спроектировать хорошую систему

С этим я часто сталкиваюсь, поскольку мои обязанности уводят меня все дальше и дальше от повседневной разработки ПО. Следить за командой разработчиков — огромный объём работы. И если вы не понимаете, на что способна ваша команда, то сможете разрабатывать решения только для самых простых проблем. И опасайтесь тех, кто давно не писал никакого кода.

8. Каждая система в конечном счёте отстой, смиритесь с этим

У Бьерна Страуструпа есть цитата: «Есть только два вида языков: те, на которые все жалуются, и те, которыми никто не пользуется». Это можно распространить и на большие системы. Не существует «правильной» архитектуры, вы никогда не закроете весь техдолг, не разработаете идеальный интерфейс, ваши тесты всегда будут слишком медленными. 

Это не оправдание тому, чтобы не делать что-то лучше, а наоборот, способ дать вам перспективу. Меньше беспокойтесь об элегантности и совершенстве, стремитесь к постоянному улучшению и созданию пригодной для жизни системы, в которой вашей команде нравится работать и которая стабильно приносит пользу.

9. Никто не спрашивает «почему» в достаточной степени

Используйте любую возможность поставить под сомнение предположения и подходы, которые «всегда делались так, как надо». В команде появился новый сотрудник? Обратите внимание, где он запутался и какие вопросы задает. Поступила заявка на новую функцию, которая не имеет смысла? Убедитесь, что вы понимаете цель и то, что требует эту функциональность. Если не получаете чёткого ответа, продолжайте спрашивать пока не поймёте.

10. Сосредоточьтесь на том, чтобы избежать 0,1х-программистов, а не найти 10х-программистов

10x-программист — это глупый миф. Идея о том, что кто-то может сделать за 1 день то, что не менее компетентный, трудолюбивый, и такой же опытный программист может сделать за 2 недели, глупа. 

Я видел программистов, которые пишут в 10 раз больше кода, а потом вам приходится исправлять его в 10 раз дольше. Кто-то может быть 10х-программистом только в том случае, если вы сравниваете его с 0,1x-программистом — тот, кто тратит время, не просит обратной связи, не тестирует свой код, не рассматривает крайние случаи и так далее. Нужно заботиться, чтобы не допустить 0,1x-программистов в команду, а не искать мифического 10x-программиста.

11. Одно из главных отличий между сеньором и джуном — свое мнение о том, как все должно быть

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

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

12. Людям не нужны инновации

Люди много говорят об инновациях, но обычно они ищут дешёвые преимущества и новизну.

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

13. Ваши данные — самая важная часть системы

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

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

14. Ищите технологических акул

Старые технологии, которые остались на плаву, — это акулы, а не динозавры. Они настолько хороши, что пережили быстрые изменения, которые постоянно происходят в мире технологий. Заменяйте их только в том случае, если у вас есть очень веская причина. Эти инструменты не будут модными и современными, но позволят выполнить работу без множества бессонных ночей.

15. Не путайте скромность с невежеством

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

Поговорите с окружающими, запросите фидбек и советы.

16. Программисты должны регулярно писать

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

17. Рабочие процессы должны быть минимально энергозатратными

Сейчас все хотят быть agile, но «agile» — это создание вещей небольшими порциями, обучение, а затем итерация. Если кто-то пытается вложить в это гораздо больше, значит, он что-то продаёт. Для этого необязательно переставать помогать сотрудникам или отказываться от отчетности, но вы когда-нибудь слышали, чтобы люди из ваших любимых IT-компаний и масштабных опенсорс-проектов хвалились тем, какой у них клёвый Scrum? Процессы должны оставаться лёгкими и гибкими до тех пор, пока не появится потребность в большем. Доверьтесь своей команде, они всё сделают.

18. Инженеры-программисты, как и все люди, должны чувствовать ответственность

Если вы отвлечёте кого-то от результатов его работы, то он будет меньше заботиться о ней. Это почти тавтология и основная причина, почему кросс-функциональные команды работают хорошо, и почему DevOps стал таким популярным. Дело не только в передаче обслуживания и неэффективности, а в том, чтобы управлять всем процессом от начала до конца и нести прямую ответственность за предоставление ценности.

Дайте группе увлечённых людей полную ответственность за проектирование, создание и выпуск софта (или чего-то еще) — произойдут удивительные вещи.

19. Собеседования не помогут определить, насколько хорошим членом команды будет человек

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

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

20. Стремитесь к созданию более компактной системы

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

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

Ваша история

Вот и всё: 20 лет разработки программного обеспечения превратились в 20 мудрых пунктов. Если согласны или не согласны с мыслями в статье, или если есть, что добавить и чем поделиться — пишите в комментариях.

Опубликовано

Как отсортировать огромный файл

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

ID  DocType NormalizedName  DisplayName Yea
12648   Book    a fancy title   A FaNcY-Title   2005
1867453 Essay   on the history of humans    On the history of humans    2016
...

Этот файл имеет размер около 67 ГБ, в сжатом виде около 22 ГБ. Я хотел бы отсортировать строки файла по идентификатору (около 300 миллионов строк) в порядке возрастания. Идентификатор каждой строки уникален и варьируется от 1 до 2147483647, могут быть пробелы. Взять и загрузить файл целиком в оперативную память не представляется возможным из-за его огромного размера. Возник вопрос как наиболее эффективно отсортировать все строки таблицы.

  1. Читаем файл частями по миллиону строк
import glob

path = "chunk_*.tsv"

chunksize = 1_000_000
fid = 1
lines = []

with open('large_file.tsv', 'r') as f_in:
    f_out = open('chunk_{}.tsv'.format(fid), 'w')
    for line_num, line in enumerate(f_in, 1):
        lines.append(line)
        if not line_num % chunksize:
            lines = sorted(lines, key=lambda k: int(k.split()[0]))
            f_out.writelines(lines)

            print('splitting', fid)
            f_out.close()
            lines = []
            fid += 1
            f_out = open('chunk_{}.tsv'.format(fid), 'w')

    # last chunk
    if lines:
        print('splitting', fid)
        lines = sorted(lines, key=lambda k: int(k.split()[0]))
        f_out.writelines(lines)
        f_out.close()
        lines = []

2. Объединяем отсортированные чанки

from heapq import merge

chunks = []
for filename in glob.glob(path):
    chunks += [open(filename, 'r')]

with open('sorted.tsv', 'w') as f_out:
    f_out.writelines(merge(*chunks, key=lambda k: int(k.split()[0])))

heapq.merge() возвращает генератор, который работает поверх исходных коллекций — поэтому не расходует лишнюю память. И он учитывает, что исходные списки уже отсортированы — поэтому не выполняет лишних действий.

Опубликовано Оставить комментарий

Новые возможности в Python 3.9

Python 3.9 в настоящее время находится на четвертой стадии бета-тестирования (по состоянию на июль 2020 года). Хотя некоторые вещи могут измениться, но теперь совершенно ясно, как будет выглядеть новая версия.

Дженерики встроенных типов в аннотациях

Начиная с версии 3.9 появилась возможность использовать привычные для нас built-in коллекции в качестве аннотаций с указанием типа содержимого этих коллекций. Напомню, что ранее для таких целей использовались объекты ListDict из модуля typing. Вот как это теперь выглядит:

def do_stuff(data: list[int]):
    pass

Вот некоторые коллекции, которые теперь можно обобщить:

  • tuple
  • list
  • dict
  • set
  • frozenset
  • typecollections.deque
  • collections.abc.Coroutine
  • re.Pattern
  • и многое другое

Объединение словарей

До Python 3.9 стандартными способами слияния с dicts были:
1. Метод .update: a.update (b)
2. {** a, ** b}
Теперь появится еще один. | Оператор объединения делает именно то, что должен: Aunion of 2 dicts:

a = {'cars': 5, 'phones': 2}
b = {'cows': 10, 'lizards': 3}
a | b
// {'cars': 5, 'phones': 2, 'cows': 10, 'lizards': 3}

Как и .update или {** a, ** b}, это может привести к потере данных, если в файле dict есть дубликаты ключей. Кроме того, этот оператор одинаково хорошо работает с расширенным назначением:

a = {'cars': 5, 'phones': 2}
b = {'cows': 10, 'lizards': 3}
a |= b
print(a)
// {'cars': 5, 'phones': 2, 'cows': 10, 'lizards': 3}

Удаление суффиксов и префиксов

Новые методы .removesuffix() и .removeprefix() для str делают это:

'SubaruImpreza`.removeprefix('Subaru') // 'Impreza' 
'SubaruImpreza'.removesuffix('Impreza') // 'Subaru'

Новый парсер

В Python 3.9 используется новый парсер. Он основан на PEG (грамматика синтаксического анализа выражения), в отличие от старой, которая использует LL (синтаксический анализатор слева направо). Это было сделано потому, что возможности синтаксического анализатора LL были исчерпаны, и стало все труднее реализовывать новые языковые функции. Скорее всего, вы не заметите никакой разницы — производительность сопоставима, а полная обратная совместимость подтверждена.
Вы должны заботиться об этом, только если ваш код использует модуль синтаксического анализа из стандартной библиотеки. Некоторое время назад она устарела и не будет работать с новым парсером. В качестве обходного пути вы можете переключиться обратно на старый анализатор, используя аргумент -X oldparser или переменную окружения PYTHONOLDPARSER = 1.

Модуль zoneinfo

В Python 3.9 появился новый модуль под названием zoneinfo. Он реализует класс ZoneInfo, который обеспечивает поддержку часовых поясов IANA.

from zoneinfo import ZoneInfo
from datetime import datetime, timedelta
timestamp = datetime(2020, 7, 15, 11, tzinfo=ZoneInfo("America/Los_Angeles"))

Модуль Graphlib

Еще один новый модуль — на этот раз для работы с графами. Прямо сейчас он реализует только алгоритм топологической сортировки для направленных ациклических графов. Если вы не поняли, что я только что написал, вам, скорее всего, не потребуется новый модуль. Для тех из вас, кто знаком с теорией графов, вот как должен использоваться модуль (взято из документации по Python):

>>> graph = {"D": {"B", "C"}, "C": {"A"}, "B": {"A"}}
>>> ts = TopologicalSorter(graph)
>>> tuple(ts.static_order())
('A', 'C', 'B', 'D')

Обновления в math

В модуле math появилось несколько интересных апдейтов, а именно:

  • функция нахождение наибольшего общего делителя теперь может принимать неограниченное количество аргументов, ранее она принимала только 2 math.gcd(10, 15, 20, 100)
  • появилась функция нахождения наименьшего общего кратного, math.lcm
Опубликовано Оставить комментарий

Django storage and s3

Сталкиваясь в процессе разработки с необходимостью иметь несколько экземпляров веб-приложения, часто ощущается необходимость иметь статику и медиа файлы в одном месте. Самый легкий способ реализовать эту это возможность — это пользоваться облачным хранилищем, например, таким как s3 от amazon.

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

setting.py
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID = '...'
AWS_SECRET_ACCESS_KEY = '...'
AWS_STORAGE_BUCKET_NAME = '...'
AWS_QUERYSTRING_AUTH = Falsemodels.py

models.py
from django.core.files.storage import default_storage as s3_storage

class Model(models.Model):
    title = models.CharField(max_length=50)
    image = models.ImageField(storage=s3_storage, upload_to='dir/')

Значение FalseдляAWS_QUERYSTRING_AUTH удаляет параметры аутентификации из сгенерированного адреса. Это применимо когда у вас публичный S3.

Для того, чтобы вся статика хранилась там же, на s3, необходимо будет выполнить команду

python manage.py collectstatic

Опубликовано Оставить комментарий

7 основных ошибок, которые делают Django-разработчики

перевод статьи 7 Common Mistakes That Django Developers Make

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

Изобретенение велосипедов

Django имеет множество функций из коробки и гораздо больше возможностей дают сторонние пакеты. Попробуйте «погуглить» проблему, которую хотите решить, прежде чем что-то писать — возможно, уже существует многофункциональное решение.

Вы также можете использовать онлайн-каталог Django Projects, где категория «apps» (небольшие компоненты, используемые для создания проектов) насчитывает более 3200 проектов. Вот краткий образец интересных пакетов только с первых двух страниц листинга:

Бонусный совет: я настоятельно рекомендую начать новый проект Django с cookiecutter-django. Он поставляется с кастомной моделью пользователя, регистрацией через django-allauth, отправкой электронной почты через Anymail и многими другими настройками по умолчанию, связанными с безопасностью и развертыванием.

Монолитная структура приложения

Django — это слабо связанная платформа, которая не требует от вас создания веб-приложений каким-либо конкретным способом. У опытных разработчиков Django, однако, есть стандартный способ делать вещи.

Основной единицей веб-приложения Django является проект Django, который состоит из одного или нескольких приложений. Приложение Django — это автономный пакет, который должен делать только одно. Например, блог, приложение участия в чем-либо или календарь событий.

Приложения Django могут содержать модули Python, специфичные для Django модули (представления, URL-адреса, модели, формы и т. Д.), Статические файлы, миграции баз данных, команды управления, модульные тесты и многое другое. Вы должны разделить ваш проект на небольшие, многократно используемые приложения, используя простую логику.

\ecommerce_project      <= This is your Django project
    \cart               <= This is a Django cart app
    \checkout           <= This is a Django checkout app
    \products           <= This is a Django products app
    db.sqlite3          <= Your project database
    manage.py           <= Django project management utility

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

Написание толстых представлений и тонких моделей

Архитектура Django может быть описана как Model-Template-View (MTV) или Model-View-Template (MVT).

Model (модель) – это то, куда должна идти большая часть вашей бизнес-логики. Он определен в models.py и находится в каталоге приложения. Он также включает в себя запросы к базе данных, которые передают результаты в слои представления и шаблона.

View (представления) состоят из кода, который обрабатывает взаимодействие с пользователем, такое как отправка формы пользователем и формирование результатов из базы данных в соответствии с вашим шаблоном. Это определено в views.py.

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

Вы должны также использовать собственные менеджеры. Например, пользовательский менеджер может предоставить метод with_counts (), который возвращает список всех объектов OpinionPoll, каждый с дополнительным атрибутом num_responses, который является результатом агрегированного запроса. Для большего количества идей, проверьте встроенный UserManager.

Слишком много запросов на представление или неоптимизированные запросы

ORM Django часто обвиняют в том, что он делает слишком много запросов или они неоптимизированы. Но мы видим, что это происходит с ORM и в других средах.

Реальная проблема в том, что мы часто не знаем о проблемах производительности и их источниках. Как только вы выясните, какие у вас узкие места, вы сможете выбрать правильный подход для их устранения. Здесь вы можете многое сделать, но, скорее всего, это будет так:

  • Исправить простые ORM-запросы (привет предварительная выборка)
  • Настройка и оптимизация запросов ORM
  • Добавьте кеширование в нужных местах
  • Предоставить больше ресурсов

django-debug-toolbar — замечательный инструмент отладки. Вы можете использовать его для отслеживания проблем с производительностью в SQL-запросах, запросах, шаблонах, кэше и т. Д. Этот небольшой пакет поможет вам быстро выявить проблемы. Я настоятельно рекомендую использовать его.

Избыточные поля моделей

Поскольку запросы не могут использовать вычисляемые столбцы, а добавление реального столбца — всего лишь «создание миграций», разработчики часто дублируют поля, которые по-разному представляют одни и те же данные.

Довольно скоро половина ваших записей модели Vehicles будет иметь is_motorcycle == True и wheel_count == 4, и вы не будете уверены, какому полю доверять (подсказка: ни одному).

С Django вы можете рефакторировать несогласованные свойства, подобные этим, с помощью декоратора @property. Однако, хотя ORM позволяет вам обращаться к столбцам как к свойствам, обратное неверно, поэтому вам придется вручную рефакторировать каждый запрос.

Отсутствие индексов в моделях

Даже опытные разработчики Django забывают об индексах. Пожалуйста, добавляйте индексы к своим моделям! С другой стороны, не индексируйте все, так как это замедлит вставки, обновления и удаления. Как правило, вам нужен индекс для всего, что вы будете использовать для фильтрации или присоединения. Проанализируйте ваши QuerySets, чтобы определить, где нужны индексы.

Непоследовательная проверка данных

Модели Django могут быть связаны с одной или несколькими «формами», которые используются для создания и обновления экземпляров модели. Форма имеет много действий по-умолчанию, в частности, проверки, которая контролируется свойствами модели. Фактически, многие свойства модели существуют только для управления поведением форм по-умолчанию.

Многие разработчики Django забывают, что модель можно модифицировать не только посредством ее формы. Они также забывают отслеживать, какие ограничения находятся где. Не-ноль? Это на модели. Определите выбор для поля, явно перечисляя, какие значения оно может иметь? Это на форме. Уникальность? На модели. И так далее.

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

Резюме

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

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

Если вам понравилась эта статья, вы должны почитать плюсы и минусы Django в качестве веб-фреймворка для разработчиков Python.

Опубликовано Оставить комментарий

Шесть лучших финансовых библиотек для Python

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

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

NumPy

NumPy является базовым модулем для выполнения финансовых расчетов с помощью Python. На 2018 год  NumPy входил в семерку наиболее популярных модулей, на данный же момент трудно найти финансиста, который бы с ним не работал. Библиотеки NumPy позволяют манипулировать матрицами и массивами, задействовать функции генератора случайных чисел, необходимые для определенных техник оптимизации вроде бустинга и бэггинга. Стоит отметить, что значительная часть основного кода здесь написана на C, что позволяет сгладить характерную для Python медлительность.

SciPy

SciPy собран из базовых функций NumPy, и крайне удобен в обработке финансовых данных, а также техниках обработки сигнала, линейной алгебре, статистике, интерполяции и оптимизации.

Matplotlib

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

Pandas

Pandas, основанный на SciPy и NumPy, является достаточно распространенной библиотекой для работы с данными и их анализом. Pandas отлично показывает себя в управлении временными данными, и является незаменимым инструментов для отслеживания изменений цен с течением времени. Важно отметить, что изначально модуль pandas создавался разработчиками AQR, и лишь впоследствии перешел в открытый доступ.

В сумме NumPy, SciPy, matplotlib и pandas составляют популярный пакет, обычно именуемый просто как NumPy / SciPy. Несмотря на популярность самого пакета, его установка связана со значительными сложностями, и часто рекомендуется устанавливать его посредством Anaconda для последующего запуска в виртуальной среде. Проблема, однако, в том, что помимо NumPy / SciPy Anaconda устанавливает еще более 200 библиотек, что может поставить под вопрос эффективность этого метода.

Scikit-learn

Еще один модуль из состава Anaconda, в 2008 году признанный самым популярным модулем машинного обучения для Python. Классификация, кластеринг и другие популярные техники машинного обучения здесь подаются с визуализацией matplotlib, основной же код базируется на уже упоминавшихся NumPy и SciPy.

QuantLib 

Значительная часть квантов работает в оценке и структурировании, и для них в Python доступна QuantLib, одна из наиболее востребованных библиотек для C++ для операций оценки и расчета финансовых деривативов. Среди преимуществ QuantLib  однозначно выделяется характерная для кода в C++ быстрота, но отсутствие специализированной документации для Python делает освоение этого модуля достаточной непростой задачей. Однако и она оправдывает затраченные усилия, предоставляя быстрый и доступный инструмент для оценки в повседневной деятельности трейдера, где библиотека, написанная исключительно на Python, оказалась бы непростительно медленной.

Опубликовано Оставить комментарий

Django formsets with attach

В Django есть отличная вещь – generic, которая содержит в себе такие конструкции как CreateView, UpdateView и т.д. Бывают ситуации, когда нам к форме модели необходимо добавить связанную сущность и записать это всё по одному сабмиту. В таком случае лучше всего прибгенуть к формсетам. Для начала необходимо описать сам формсет, который хотим использовать вместе с формой

from django.forms.models import inlineformset_factory
ImageFormSet = inlineformset_factory(Product, Image, extra=1, fields=['image'], can_delete=True)

и вот в самом UpdateView надо переопределить несколько методов:

class ProductUpdate(ProductMixin, UpdateView):
    def form_valid_formset(self, *args):
        for formset in args:
            if formset.is_valid():
                formset.save(commit=False)
                # Если нажали удалить у дочернего объекта
                for obj in formset.deleted_objects:
                    obj.delete()
                formset.save()
            else:
                return HttpResponseRedirect(self.get_success_url())

    def form_invalid_formset(self, *args):
        return self.render_to_response(self.get_context_data(**dict((a, a) for a in args)))

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.form_class
        form = self.get_form(form_class)
        return self.render_to_response(self.get_context_data(form=form, image_form=ImageFormSet(instance=self.object)))

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form(self.form_class)
        image_form = ImageFormSet(self.request.POST, self.request.FILES, instance=self.object)
        if form.is_valid():
            return self.form_valid_formset(image_form)
        else:
            return self.form_invalid(form) 

Вот так быстро можно сделать вложения в момент создания и редактирования