Записки разработчика
28 subscribers
22 photos
4 files
131 links
Заметки о используемых инструментах и технологиях, прочитанных статьях и книгах, размышления о саморазвитии и решении прикладных задач.
Download Telegram
Нельзя сделать forward declaration на класс, объявленный через using.
Как автоматизировать тестирование питоновского пакета на разных питонах?
Для этого есть https://tox.readthedocs.io/en/latest/ и https://github.com/pyenv/pyenv.
В tox можно указать все версии питона, на которых следует тестировать, а с помощью pyenv установить любую версию.
Язык Си — как секс для подростков:
— Он у всех на уме
— Все постоянно о нем говорят
— Все думают, что все остальные это делают
— Никто на самом деле этим не занимается

А те немногие, кто правда это делают — делают это плохо, небезопасно и думают, что в следующий раз будет лучше.
:)
IWOMM — It works on my machine!
https://www.appveyor.com/
Клевый инструмент для CI, бесплатен для open source, поддерживает винду и убунту.
Интеграция из коробки с гитхабом.
Пример:
https://github.com/zifter/expression_fetcher/pull/2
Понравился проект? Купи пиво в благодарность!
Именно такой слоган мог бы быть у сервиса https://beerpay.io. По факту это интересный сервис для мейнтейнера опен сорс проекта получить денежное вознаграждение за свои труды.
Со стороны донатера все выглядит очень просто - кидаешь денег за спасибо или кидаешь денег на какие-то фичи, которые можно так же предложить реализовать. Так сказать голосование рублем.
Со стороны мейнтейнера все почти так же радужно, нужно всего лишь:
1. Подключить сервис к своему github аккаунту
2. Указать проект за который хочется получать пожертвования. При этом сервис предложит добавить в README.md бейджи с ссылками (Пример)
3. Подключить аккаут beerpay к аккаунту stripe (новая платежка).
4. Для мейнтейнеров из СНГ - расстроиться, что stripe не доступен для них.
5. Понять, что бесполезен без возможности вывести деньги :)
Наверное все замечали бейджики на страницах проектов github с клевыми статусами "codecoverage 100%", "build: passing", "python: 27".
Зачем это и самое главное как сделать?
Ответ на первый вопрос для меня оказался самым удивительным, так как он нашелся в научной статье, посвящённой конкретно этой теме. Можно посмотреть сокращенную и более удобную для чтения версию здесь.
Авторы разделяют бейджы по типам сигнала, которые они несут:
* уловные - предоставляют информацию или указывают на принятые соглашения (лицензия, стандарт языка, код стайл);
* оценочные - ассоциированы со сторонними сервисами, которые вычисляют какие-либо метрики проекта (тестовое покрытие, статус тестов, свежесть зависимостей).
И на основе проекта npm они статистически доказывают, что есть корреляция между, например, качеством тестового покрытия, свежестью зависимостей и вовлеченностью контрибьютеров. В общем, советую ознакомится.
А вот "как сделать?" оказалось достаточно простым вопросом - есть сервис тех же авторов научной статьи, который позволяет сделать интеграцию с кучей существующих сервисов (travis-ci, teamcity, appveyor, github, pypi, beerpay и пр.). Можно выбрать бейдж из существующих или сделать кастомный. Все элементарно, к счастью 🙂
Если у вас есть своей проект и вы желаете его развивать - смело интегрируейте. И первым, с чем нужно интегрироваться, автоматизированный запуск тестов. Выше я привел пример с appveyor, а дальше будет пост про travis-ci.
DDD - Domain-Driven Design
Как можно поднять приоритет оверлей значка на иконке в Windows? Очевидно же влепив кучу пробелов перед именем оверлея иконки в регистре! Первое место занимает OneDrive с 4-мя пробелами, второе место Dropbox c 3-мя и почетное третье TortoiseGit c 2-мя! Неудачная логика оверлеев иконок приводит вот к таким костылям :( И при этом эти оверлеи иконок постоянно еще и восстанавливаются, если удалять неугодные.
C++
Примеры частых ошибок (по мотивам статьи C++ Antipatterns)
* Чтение из istream без проверки результата
Всегда нужно проверять, что в итоге прочитали, так как велик шанс получить мусор в переменных
int i, j, k;
if (in >> i >> j >> k)
{
std::cout << calculate(i, j, k);
}
* Проверка istream.eof() в цикле
Мы можем уже достигнуть конца потока при чтении, поэтому правильно проверять результат чтения сразу
while (in >> x)
{
process(x);
}
* Явная блокировка и разблокировка std::mutex
В примере ниже в случае бросания исключения в секции // do мьютекс не будет освобожден:
std::mutex mtx;
void func()
{
mtx.lock();
// do
mtx.unlock();
}
Поэтому всегда используем RAII для захвата ресурсов
{
std::lock_guard<std::mutex> lock(mtx);
// do...
}
* Вставка в контейнер умного указателя через emplace_back(new X)
Если в процессе вставки происходит переаллоцирование памяти, в результате которого неожиданно не хватит памяти, то будет кинуто исключение std::bad_alloc.
В таком случае умный указатель не будет создан, поэтому объект, созданый через new, утечет.
Правильнее сначала создавать умный указатель, а потом его вставлять в контейнер.
{
v.push_back(std::make_unique<X>())
}
Кстати, здесь безразницы что использовать, emplace_back или push_back.
* Реализция оператора меньше (больше, равно и прочее)
Этот код работать не будет:
inline bool operator<(const X& l, const X& r)
{
if (l.a < r.a)
return true;
if (l.b < r.b)
return true;
return false;
}

X x1{1, 2};
X x2{2, 1};
assert( x1 < x2 );
assert( x2 < x1 );
Правильный путь, который гарантирует порядок:
inline bool operator<(const X& l, const X& r)
{
return l.a < r.a && l.b < r.b;
}
А вот это С++11 try-way
inline bool operator<(const X& l, const X& r)
{
return std::tie(l.a, l.b) < std::tie(r.a, r.b);
}
* Использование std::string("") для создания пустых строк
Дефолтный конструктор уже создает пустую строку, а вот конструктор с const char *, скорей всего, сделает аллокацию памяти.
В машине мне нравится слушать АвтоРадио, где проигрываются хиты (и не только) рок музыки.
И самое приятное что на приемнике я всегда вижу название и исполнителя песни. Но как? Это ведь радио.
Оказывается, есть стандарт RDS, который описывает передачу информационных сообщений по каналам радиовещания.
Благодаря этому стандарту мы как раз и можем принимать названия станций, исполнителей и песен. Кроме этого можно передавать любую другую текстовую информацию - рекламу, расписание передач, заказчика песни, информацию о дорожной обстановке, предупреждение о чрезвычайных ситуациях. Позволяет слушателю осуществлять поиск интересующих его станций по типу (музыка, развлечение, новости и пр), автоматически настраивать громкость и даже осуществлять навигацию транспорта.
Очень рекомендую почитать для ознакомления
Как кодируется и декодируется сигнал
На что способен и чуть подробностей
Поделюсь своим любимым факапом.
Года четыре назад у нас наблюдалась проблема со сборками билдов на TeamCity. Не помню почему, но конфигурация не ревертала локальные изменения, сделанные скриптами сборки во все возможных репозиториях. Волевым решением было принято - берем под контроль и пишем свой скрипт. И, конечно же, вызывался писать этот скрипт я.
Все шло чудесно - требования собраны, код написан, юнит-тесты добавлены, комментариями посыпано знатно. Скрипт получился добротный, локальная копия выглядела девственно чистой, как после клона. И вот, перед отправкой на ревью, мне приходит в голову гениальная мысль протестировать весь флоу работы скрипта. Догадались уже что случилось?) Да, он к чертям удалил все мои наработки за день. К счастью, сам скрипт восстановить не составило труда - он был открыт в PyCharm. А вот юнит-тесты с тестовыми данными пришлось накидать снова. Из этой истории я вынес пару уроков - делай коммиты чаще и никогда не тестируй на локальной копии 🙂
Что нужно знать (веб-)разработчику о взаимодействии в сети?
В первую очередь, это немного базовой теории об устройстве сети в целом (очень интересно!)
Основные сетевые термины и сетевые модели
Протоколы верхнего уровня (по желанию, далее подробнее)
Протоколы нижних уровней (транспортного, сетевого и канального)
Понятие IP адресации, масок подсетей и их расчет
И, конечно же, про конкретные протоколы:
# как работает udp и tcp, знать разницу
# знать на отлично http
# хоть раз скачивать файл по ftp
# понимать основы криптографии, а именно алгоритмы:
* Протокол Диффи — Хеллмана
* RSA
* и держать в уме самую частую уязвимость
# конечно, же знать как работает ssl и tls
# везде на своих сайтах использовать https
# ходить только по ssh
# пользоваться websocket
# и полюбить очереди - amqp

Есть клевая статья на английском, как будут работать протоколы ip/tcp/http/https все вместе.
В принципе все покрывается статьями с теорией, но некоторые выводы стоят того, чтобы прочитать.
Приятно чтения)
Недавно начал играть и смотреть игры по StarCraft2. Наткнулся на интересную серию игр ИИ DeepMind против прогеймеров:
https://www.youtube.com/watch?v=FEFxLpv-rZM
И соответствующий анализ игры ИИ.
https://www.youtube.com/watch?v=FFJRd9l6kW4
Довольно интересно понимать, какие игровые приемущества получает DeepMind только за счет того, что это компьтер. Например, невидимые юниты становятся для него не такими уж и невидимыми за счет обычного эффекта блюра.
"Я не боюсь ИИ который пройдет тест Тьюринга, я боюсь ИИ, который его намеренно завалит"
В общем, рекомендую.
Задача от yandex на вакансию "Разработчик беспилотных автомобилей":
Двое игроков играют в игру с карточной колодой.
Игрок А делит стандартную колоду из 52 карт на две стопки карт по своему усмотрению с единственным ограничением: в каждой стопке должна быть хотя бы одна карта.
Игрок Б случайным образом выбирает одну из двух стопок карт (каждую из стопок он может выбрать с одинаковой вероятностью, 50%), после чего вытаскивает одну случайную карту из выбранной стопки.
Как следует действовать игроку А, чтобы максимизировать вероятность вытаскивания игроком Б карты черной масти, и чему будет равна эта вероятность?
Какой минимальной вероятности вытаскивания можно достичь и каким образом? Ответы обоснуйте.

Нужно максимизировать условие:
max(P(A)) = ?
где A - событие вытаскивания игроком карты черной масти.

Выразим эту вероятность через другие:
P(A) = P(A B1) + P(A B2) = P(A|B1) * P(B1) + P(A|B2) * P(B2)
где P(A|Bi) - вероятность вытащить из i колоды черную карты
P(Bi) - вероятность выбрать i-ую колоду

P(A|Bi) = bi/(bi + ri)
где bi - количество черных карт
ri - количество красных карт

Сумма, очевидно, черных и красных карт должна быть равна 52.
Для нашего случая получаем:
P(A|B1) = b1/(b1 + r1)
P(A|B2) = (26-b1)/(52 - b1 - r1)
P(A) = (b1/(b1 + r1) + (26-b1)/(52 - b1 - r1))/2

Максимум достигается при b1 = 1, r1 = 0. Вот тут хз как доказать, вроде очевидно.
Тогда в первой колоде всего 1 черная карта (вероятность вытянуть черную карту 100%),
а в другой 25 черных карт и 26 красных (вероятность 48%)
P(A) = (1/(1 + 0) + (26-1)/(52 - 1 - 0))/2= (1 + 25/52)/2 ~ 74%
Если хотим минимизировать, очевидно, вероятность 26%.