Pull to refresh
356
31.6
Alex Efros @powerman

Systems Architect, Team Lead, Lead Go Developer

Send message

В Go и многих других языках её нет. Что до 100500 — у меня в текущем проекте на 30к строк кода — 20 интерфейсов (и только штук 12 из них для DI и тестов).

Я вот не понял, это что, извращённый аргумент из серии "не исключено, что вам придётся когда-нибудь в будущем помучаться с этим простым инструментом, поэтому давайте вместо этого продолжать мучиться сегодня со сложным"?

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

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


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

Это чушь. У меня соц.сетей кроме хабра нет и никогда не было (ну, есть линкедин, но там только резюме выложено, общаться там с кем-то кроме HR-ов мне даже в голову не приходит). Никогда это ничему не мешало.

основные замечания на код ревью о форматировании и стиле

В идеале за этим должны следить тулза для форматирования (а-ля gofmt, но такие есть не для всех языков, к сожалению) и линтер (а вот это вроде бы есть для всех). И как раз упоминания линтера я не заметил в описании Вашего окружения.


Команда в целом юнит тесты пишет из под палки и часто низкого качества

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


Не согласен, думать по определению дороже чем не думать.

Это правда. Но во-первых у нас профессия такая, что думать входит в должностные обязанности, а не думать быстро превращается в саботаж проекта. И во-вторых оно дороже здесь и сейчас. А в перспективе месяца-двух — уже совсем наоборот получается.


нужно написать предложение / поревьюить дизайн, убедить что дизайн «оптимальный»

Вы, возможно, не поняли. Я про не "архитектуру" говорил, а про "чистую архитектуру". Для первого всё, что Вы написали абсолютно валидно. Но "чистая архитектура" во-первых никоим образом не заменяет необходимость в обычной, хоть и называется похоже, и во-вторых никоим образом не конфликтует с обычной (ну, по крайней мере я не видел адекватных архитектур, которые бы конфликтовали с чистой).


Вкратце, вся "чистая архитектура" сводится к тому, чтобы бо́льшую часть кода изолировать от внешнего мира (и тем самым сильно упростить её тестирование). Для этого эта часть кода (по сути — бизнес-логика, или в других терминах Use Cases и Entities) должна зависеть от интерфейсов везде, где ей нужен внешний мир (отправлять запросы по сети, работать с файлами/БД), которые можно будет мокать в тестах. Остальной код (адаптеры к внешнему миру, они же Controllers/Presenters/Gateways) пишется в виде минимальной, тонкой прослойки, которая просто занимается конвертацией данных в формате внешнего мира (API собственный и других сервисов, форматы файлов, структура БД) в форматы бизнес-логики (типы/классы/структуры объявленные в части кода с бизнес-логикой). Такие адаптеры чуть сложнее тестировать, потому что нужно уже как-то или мокать внешний мир (поднимать мок-сервисы на случайном порту, например) или использовать медленный интеграционный тест с настоящей БД — но только чуть, потому что сложность создания необходимой для них внешней среды компенсируется простотой самих тестов т.к. код в этих адаптерах очень простой, логики в нём толком нет, просто конвертация данных и ошибок. (Разумеется, адаптеры так же зависят не от конкретного типа реализующего бизнес-логику, а от интерфейса, который мокается в тестах адаптеров.) Собственно, "цена" которая платится за "чистую архитектуру" заключается именно в том, что вместо, как некоторые пишут, одной структуры данных, которая и по API ходит, и бизнес-логикой обрабатывается, и в БД пишется/читается — теперь их нужно три разных, и код конвертирующий между ними (ну и сам код, разумеется, нужно на три части разделить, но на его сложности или объёме это практически не сказывается). Но эти конверторы абсолютно тупые, простые (некоторые их даже генерируют автоматически), и их написание и поддержка не требует заметного времени.


Я веду к тому, что тут не о чём дискутировать или согласовывать. Разделение кода по требованиям "чистой архитектуры" — это жизненная необходимость чтобы он стал легко тестируемым. Единственный вариант, когда она не нужна — это когда код не требуется тестировать юнит-тестами.


Я вижу, что даже если люди пишут юнит тесты, это ничего не гарантирует.

Юнит-тесты гарантируют ровно одно: что код работает именно так, как этого ожидает написавший его разработчик (и это основная причина, по которой нельзя делегировать написание юнит-тестов джунам — их должен писать тот же, кто написал код этого PR). Если разработчик некорректно понял бизнес-требования, или архитектор налажал и проект не собирается в целое, или API внешнего сервиса не соответствует нашим ожиданиям — юнит-тесты не выявят такие проблемы, но это вовсе не означает, что они бесполезны. Их польза складывается из:


  • почти весь код "запускается" хотя бы раз, что сильно уменьшает количество неприятных крешей в продакшне из-за того, что только в продакшне какой-то код реально впервые запустился
  • разработчик получает уверенность, что написанный им код — рабочий, и работает именно так, как он задумывал (если честно, лично я вообще не понимаю, как без этого можно с чистой совестью закрывать тикет!)
  • мы автоматом получаем регрессионное тестирование, что сильно ускоряет внесение изменений в код, потому что нет страха что-то неявно сломать и не заметить (и это даже важнее предыдущих пунктов)

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

Беда не тогда, когда про SOLID ничего не знают, а когда про него знают очень крепко, но неправильно. Потому что в этом случае они начинают городить ту ещё "архитектуру".

Ну, включая в nginx поддержку njs или openresty надо отдавать себе отчёт, что безопасность от этого пострадает. Впрочем, конкретно в openresty реальная уязвимость пока только одна, а вот в njs — беда, да.

Главное достижение WireGuard — он показал, что настройка и реализация VPN могут быть очень простыми и при этом более чем эффективными. Остальным VPN (особенно будущим) теперь придётся конкурировать с учётом этого. И за это WireGuard большое спасибо. А в остальном, WireGuard или что-то другое — не так уж и важно.

А разве при использовании SoftEther эта фича с VPN over HTTPS работает только при использовании SSTP? Мне почему-то показалось, что это фича самого SoftEther, так что полагаю ещё какие-то из поддерживаемых им протоколов должны такое уметь.

SoftEther это немного другая история — он поддерживает кучу протоколов, поэтому неясно, а чего ради из них всех предпочитать именно SSTP.


WireGuard есть примерно вообще под всё: https://www.wireguard.com/install/


Волк может натянуть овечью шкуру, но останется волком.

Ну тогда надо использовать описанный в статье вариант, с маскировкой VPN-трафика под HTTPS.

Если он стоит рядом, и они ощутимо проседают — Вы что-то не так настроили, потому что в нормальных условиях этого происходить не должно. Попробуйте взять тот же WireGuard, он достаточно быстрый, жрёт мало ресурсов, и его практически невозможно "настроить" (т.е. его сложно настроить некорректно :)), и проверьте с ним. Плюс неплохо убедиться, что сервер на котором стоит VPN не перегружен другими задачами.

Холивора не получится. Я вот в первый раз услышал про SSTP (что не удивительно, учитывая что он принадлежит M$, а я их продукты не люблю), но уже вполне в состоянии ответить на вопрос "почему не":


Оффтопик, но что касается envoy лично меня смущает большое количество CVE — не хочется завязывать критичные элементы инфраструктуры на настолько дырявый софт.

Судя по примеру кода выше и статьям Вы пишете на JS. DIP для тестирования важен в языках, в которых нет возможности влезть внутрь чужого объекта и что-то там подменить на мок средствами самого языка (т.е. это Ваше "чудесно" актуально только для некоторых языков, и далеко не всё в этих языках так же чудесно). Ещё он важен в компилируемых языках, в которых мы не хотим перекомпилировать и релизить приложения под все платформы из-за не относящихся к этим платформам изменений просто потому, что у нас такой граф зависимостей что перекомпиляция всего происходит вынужденно.


P.S. И я не ассоциирую DIP с тестируемостью, я приводил тесты как одну из (обычно основную) причин появления второй реализации интерфейса, существование которой становится причиной для выделения интерфейсов и использования DIP.


P.P.S. Впрочем, Вы правы в том, что если автор тоже пишет на скриптовом языке, то есть высокая вероятность что у него и без DIP нет проблем с тестированием и моками, и равно как и проблемы с избыточными перекомпиляциями.

Если убрать словесную эквилибристику, то получится, что второй код зависит от требований первого пользователя. ЧТД.

Неверно. Получится, что мы явно обозначили границу между требованиями первого и второго заказчиков: первый имеет право как угодно определять требования к сортировке задач одного исполнителя, второй может менять что угодно кроме внутреннего порядка задач одного исполнителя. И пока эта граница не нарушается — требования обоих заказчиков можно реализовывать независимо друг от друга, не боясь что-то сломать, и не держа при этом в голове требования обоих сразу. А когда требования одного из заказчиков (нечаянно) её нарушат — будет высокая вероятность это заметить (благодаря тому, что в своё время эту границу определили явно) и вместо траты времени на реализацию "в лоб" и потом вылавливание багов можно будет вернуться на этап проектирования ТЗ и обсудить изменения этой границы либо отмену новых требований.

Если это был ответ мне, то Вы промахнулись мимо кнопочки "ответить". Предположим, что мне.


Написанное (не всё, конечно) я регулярно перечитываю и дополняю, разумеется, иначе зачем его вообще писать. Но я пишу либо в стиле больших TODO-списков с подразделами по разным темам, либо в стиле опять же больших инструкций-howto, либо опять же списков с заметками по какой-то теме (напр. список полезных фич и багов выявленных при изучении новой/альтернативной версии какого-нибудь софта).


Иными словами, документов у меня не так много (штук 80), они довольно большие (строк 100-200), и между ними нет ссылок (есть группировка по подкаталогам, но их всего десяток). Описанный же в статье подход подразумевает совершенно иной подход, и хотелось бы понимать его плюсы/минусы прежде чем отметать по причине "меня всё устраивает в текущем подходе" — а вдруг новый окажется удобнее?

Да, спорный. Не могу сказать, что я полностью разделяю точку зрения автора. Но однозначно интересный и полезный на уровне "принять к сведению" как минимум.

Почему? На мой взгляд рут нужен в первую очередь потому, что это единственный способ стать владельцем собственного устройства, а не его арендатором. Во вторую очередь он нужен потому, что без него не будет ни AFWall+, ни AdAway, ни Titanium Backup — а на мой взгляд это довольно критичные инструменты для комфортного использования устройства.

Information

Rating
152-nd
Location
Харьков, Харьковская обл., Украина
Date of birth
Registered
Activity