en
Feedback
StringConcat - разработка без боли и сожалений

StringConcat - разработка без боли и сожалений

Open in Telegram

Полезный блог от разработчиков для разработчиков. Наш сайт: howto.stringconcat.ru

Show more
3 707
Subscribers
+224 hours
+117 days
+730 days
Posts Archive
В прошлом посте мы писали, что разрабы не умеют инкапсулировать и у них модули внутренностями вовне светят. Можно подумать, что так делают только джуны, но нет. Так пишут и солидные дядьки с бородой. И речь не об энтитях, что мы сохраняем в базу данных, а о модулях в принципе. Если это библиотека, значит, ей будет невозможно пользоваться без предварительного изучения внутренностей. Если что-то спрятанное за интерфейсом, придётся найти реализации и смотреть, в каком порядке что вызывать. В микросервисах — выяснять, на каком стеке он сделан и какая СУБД пользуется. В общем, подумайте немного над этим вопросом, когда пилите очередной модуль, ибо отклонение грозит повышенной связностью. А это плохо. В той же dora пишут, что низкая связность увеличивает производительность разработки софта. Благотворность низкой связанности, на наш взгляд, справедлива и для внутреннего дизайна. Потому как о какой производительности мы можем говорить, если у нас всё знает про всё?

Теперь немного подушним. За свою карьеру я-таки заметил одну вещь, от которой у меня пригорает. Многие разрабы не умеют в инкапсуляцию, от чего кишки классов и модулей часто вываливаются наружу. Рассмотрим на примере. Представим что у нас есть вот такой класс:

class Disease {
 var confirmed: Confirmed
}

enum class Confirmed {
 YES, NO, NOT_SPECIFIED
}
Мы можем подтвердить диагноз или отклонить его. Как бы вы реализовали? Нам обычно попадается такое:

fun setConfirmed(confirmed: Confirmed){
 // какие-то проверки
 this.confirmed = c
}
У такой реализации есть недостатки. Клиент теперь чуть больше знает о реализации вашего модуля: оказывается, есть какой-то енумчик, который нужно передать внутрь. Ещё это сложно рефакторить: как найти все места, в которых передается Confirmed.YES, учитывая что значение не везде передается константо? А если мы захотим поменять YES на CONFIRMED, сколько классов придется поправить? А можно ли передавать в метод NOT_SPECIFIED или же мы получим ошибку? Пример примитивный, но объём кучи навоза уже можно прикинуть. И многие разработчики не думают, как грамотнее инкапсулироваться, вываливают всё наружу, а потом жалуются, что у них всё слиплось. Правильнее сделать примерно так:

fun confirm(){
 // какие-то проверки
 this.confirmed = Confirmed.YES
}

fun decline(){
 // какие-то проверки
 this.confirmed = Confirmed.NO
}

fun confirmed() = this.confirmed == Confirmed.YES
Методов больше, но зато внешний клиент знает меньше про устройство модуля, мы легко можем найти все вызовы без угадайки. К тому же светить Enum может оказаться совсем необязательным, ибо с точки зрения предметки нас интересует только факт подтвержденности диагноза, а что там внутри за статусы — вообще пофигу. Но это ладно, когда мы знаем какой параметр передать, — это самый легкий случай. Иногда нужно знать последовательность вызовов или даже тайминг. Вообще, степень такой связности обозвали даже специальным словом Connascence. Поэтому, когда вы пишете модуль, подумайте над следующим: - Что вы можете скрыть и не показывать? - Какие изменения внутри вашего модуля могут затронуть клиента? Вы удивитесь, насколько проще клиенту будет работать с вашим модулем.

Буквально мы с Серёжей
Буквально мы с Серёжей

Мы с @slobodator заключили джентльменское пари на 50 евро: смогу ли я довести до конца обучение слепой 10-пальцевой печати ил
Мы с @slobodator заключили джентльменское пари на 50 евро: смогу ли я довести до конца обучение слепой 10-пальцевой печати или брошу это занятие и вернусь к старой доброй традиции печатать 4,5 пальцами. Андрей ставит на то, что я брошу! Срок: 2 месяца Минимальна скорость печати: 150 зн\мин Пока я полон оптимизма и новая клавиатура подпитывает меня. Вернусь к вам через 2 месяца 😎

Случилось то, что неизбежно происходит с каждым энтузиастом эргономичного рабочего места — я обзавёлся сплит клавиатурой, а к
Случилось то, что неизбежно происходит с каждым энтузиастом эргономичного рабочего места — я обзавёлся сплит клавиатурой, а конкретнее — ZSA Moonlander. Эта идеальная игрушка для гика помогает от боли в локтевом нерве и причиняет иную боль. Давайте по порядку. Преимущества Слои раскладки. Все сплиты глубоко кастомизируемы, а потому вам больше не потребуется ломать пальцы на шорткатах в четыре кнопки. Настраиваете слои раскладки и получаете, например, такое: — Hold T — открыть новую вкладку в браузере — Hold W — закрыть текущую вкладку — Отдельная клавиша на скобки (), чтобы не зажимать Shift — Отдельная клавиша $, чтобы ещё быстрее набирать $foo = $bar — Свой слой макросов для Idea, чтобы не упражняться в йоге для пальцев, пытаясь быстро выжать ⌥+⌘+L одной левой Можно настраивать раскладки всё свободное время. Что может быть лучше, чем сидеть по вечерам и раскидывать по слоям скобки и макросы, ощущая интеллектуальное превосходство над ~98,51% населения планеты? Ещё одно преимущество — клавиатура выглядит как пульт космолёта и никто, кроме вас, не сможет с ней работать. Вы тоже не сможете первое время, но это мелочи. Как клавиатура делает больно Производитель честно предупреждает, что первый месяц будет мучительно больно — Скорость печати показала отрицательный рост. Было 60 слов в минуту, стало 15 — Новый ZSA Moonlander стоит под 400 $, но я купил БУ за полцены — Придётся покупать вторую домой. Говорят, если привыкнуть, на обычной уже работать не хочется Как я докатился до этого Раньше я жил как нормальный человек, но потом нашёл на сингапурской свалке кресло Herman Miller Embody, которое в магазине стоит полторы тысячи американских долларов. Находка положила начало моему пути эргономиста. Я стал сидеть прямо, с локтями на подлокотниках и ладонями на клавиатуре. Но с обычной это оказалось неудобно, поэтому я обзавёлся сплитом. Через месяц напишу об ощущениях и результатах.

Вышел Thoughtworks Technology Radar #30 105 пунктов и 4 главные темы: Искусственный интеллект в помощь разработчикам. GitHub
Вышел Thoughtworks Technology Radar #30 105 пунктов и 4 главные темы: Искусственный интеллект в помощь разработчикам. GitHub Copilot, Codium AI, , Aider и Continue оказывают влияние на каждый аспект жизненного цикла разработки ПО. Якобы open-source лицензии. Новые модели лицензирования мешают экосистеме открытого программного обеспечения. Мы призываем технологов уделять пристальное внимание деталям лицензий продуктов, которыми они пользуются. Пулл-реквесты, помогающие в continues Integration, а не мешающие ей. Пул-реквесты без сомнения отличный инструмент, но они могут вредить процессу разработки, замедляя разработчиков и внося ненужную суету. Этот Радар показывает как можно использовать пул-реквесты более эффективно. Архитектурные паттерн для LLMs (Больших языковых моделей). Казалось бы только появились эти ваши Chat-GPT и прочее, а уже есть гайдлайны по архитектуре. Скачать радар #30 Не забудьте репостнуть коллегам!

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

Чем старше я становлюсь, тем меньше у меня требований к программистам. Но больше к лидам… Сегодня я проводил техническое собеседование в Thoughtworks с парнем, у которого 2 года опыта. И готовясь к интервью я думал “господи, да чего от тебя хотеть то”. На кодинг интервью уже проверили что человек знает с какой стороны к клавиатуре подходить. А мои требования просты: - Под себя не ходишь - Можешь связно говорить, не роняя слюни - Имеешь абстрактное мышление - Показываешь что есть искра в глазах И мне этого достаточно, чтобы взять в команду. А дальше уже сам. Все равно у нас все заавтоматизировано так, что накосячить будет негде. Но вот еще лет 5-7 назад я бы его гонял и в хвост и в гриву. А вы замечаете за собой похожее?

Мы разрабатываем финансовое приложение, хранящее номер кредитной карты. Аналог PayPal Как бы вы гарантировали что номер кредитной карты не попадет в логи? Вот что я ответил на собеседовании: ⁃ Нельзя фокусироваться только на бекенде, нужно рассмотреть весь путь карты от веб-браузера и до БД. ⁃ Как можно раньше в приложении обернуть Номер Карты в объект CardNumber, у которого нет метода getCardNumber(): String. Но нам же его надо будет положить в базу данных, поэтому создадим getEncryptedCardNumber(). - Не забываем переопределить`toString()` чтобы он возвращал, что-то типа 4565-****-****-**** Теперь можно отдавать Джуну логировать. ⁃ В базе данных храним номер карты зашифрованным (шифруем на ключ пользователя или сервера — отдельная дискуссия) ⁃ Когда создаем инстанс CardNumber(cardNumber: String) то сразу же шифруем номер карты, и не храним его в открытом виде, чтобы ни случайный StackTrace нас не выдал ни Дамп памяти ⁃ Сканируем все логи ищя паттерн кредитной карты. Это и логи nginx, и балансировщиков и логов приложения и пр. ⁃ Сканируем логи тестов при сборке. Нашли номер кредитки — роняем билд ⁃ Но все равно остается опасность, что несмотря на то что мы спрятали номер карты как можно раньше в нашем приложении, он будет залогирован где-то на ранних этапах, типа балансировщиков. Поэтому можно предложить шифровать номер карты сразу на клиенте, используя публичный ключ сервера, и прямо в таком виде сохранять его в БД. И мы гарантируем что на всем пути от веб-браузера и до БД номер карты не попадет в открытом виде ни в какие логи.

Задачка на гибкость ума #1. Мы разрабатываем финансовое приложение, хранящее номер кредитной карты. Как бы вы гарантировали что номер кредитной карты не покинет пределы процесса (не попадет в логи, не будет отправлен в брокер сообщений, не будет сохранен в открытом виде в БД и т.д.) ? Эту задачку мне задали на реальном собеседовании. И мне она показалась интересной для брейншторма. Поделитесь что бы вы ответили в комментариях. А следующим постом я опубликую что ответил я

Из какого вы города?
Anonymous voting

Из какого вы города?
Anonymous voting

Внимание, друзья! Инсайдерская новость для всех, кто стремится преуспеть на собеседованиях! Мы готовим новый курс по мастерству прохождения собеседований! И нам очень нужны ваши советы. Все мы знаем, что наша индустрия сломала собеседования. Прохождение собеседований стало отдельным видом искусства. И мало коррелирует с реальной работой. Если подход изменить невозможно, то по крайней мере мы упростим жизнь кандидатам. В программе курса: 🔹 Мастерство самопрезентации и составления резюме – уроки у лучших, ведь кто, как не индусы, знают эту тему лучше? 🔹 Секреты прохождения кодинг-интервью, чтобы сделать их менее стрессовыми 🔹 Полезные советы по системному проектированию 🔹 Как успешно пройти проверку на «культурную совместимость» с компанией 🔹 Искусство торговли за лучший оффер 🔹 Как определить, подходит ли вам компания и ее культура 🔹 Советы по карьере Но мы не ограничиваемся только этим. Что вас еще волнует на собеседованиях? Какие проблемы встречаются чаще всего? Пишите в комментариях, и мы обязательно учтем ваши предложения при создании курса! 💬

Кто с GraphQL работал, над мемом не смеется. Решение выглядит по-джуниорски, но у GrpahQL были веские причины сделать именно
Кто с GraphQL работал, над мемом не смеется. Решение выглядит по-джуниорски, но у GrpahQL были веские причины сделать именно так. Прохладная былина как не надо В Проде перестал отвечать один из сторонних сервисов, возвращающий квитанции. Точнее отвечал HTTP 400 Кодом. Пошли к разработчикам сервиса выяснять. Было несколько версий: — Такой квитанции нет и никогда не было — Квитанция есть, но связанные с ней сущности не нашлись — Нам не хватает прав, чтобы получить эту квитанцию, и сервис делает вид, что её нет — Изменился URL запроса квитанции За три часа дебага, вычитки логов и коммитов за последние два дня мы выяснили, что запросы вообще не приходили на сервер. Ни на один. Оказалось, админы поменяли маршрутизацию, и 400 отдавал какой-то левый сервер. Почему мы так долго возились? Потому что ошибки HTTP-протокола не были отделены от ошибок бизнес-логики. Получил 400 и надейся, что подробности будут в теле сообщения. А там их нет, ахах. А как в GraphQL 1. Если запрос дошел до endpoint’а, в любом случае вернется HTTP 200 и один из ответов, прописанных в схеме. Например, Receipt | ReceiptNotFound | NotEnoughPermissions. 2. Вернулось что-то отличное от 200 — ищи проблему в инфраструктуре. Что это даёт: — Клиенту не надо гадать, какую ошибку вернёт сервер на конкретный запрос. Все прописано в схеме. — Невозможно спутать ошибку бизнес-логики с инфраструктурной. — Не нужно обсуждать всей командой, какой код ответа использовать для бизнес-ошибок: “I am Teapot” или что-то более традиционное. Если у вас нет GraphQL и публичный API Выберите какой-нибудь разумный код для ошибок бизнес-логики. Никогда не возвращайте 200 и подробности в теле. Разработчики проверят, что вернулся 200 и посчитают, что всё хорошо. Снабжайте ответ подробностями: что произошло и как это исправить. Делайте хорошо. А плохо не делайте. Мир вам. Кстати, какой HTTP статус вы используете для ошибок бизнес-логики?

Кому знакома эта фраза?
Anonymous voting

После релиза целый спринт дадим на рефакторинг!
После релиза целый спринт дадим на рефакторинг!

Но если у тебя есть тесты и нормальный CI/CD, то так уж и быть
Но если у тебя есть тесты и нормальный CI/CD, то так уж и быть

Когда-то я работал в одной небольшой компании. Писали сложную слоёную штуковину с десятками таблиц в БД и кудрявой бизнес-логикой. Над нами стоял технический погонщик, который принуждал всех писать тесты на каждый метод сервиса. Тесты для слоёнки писать было сложно и занудно. Зато, когда QA находили баг и я лез в глубины бэка искать его причины, погонщик спокойно спрашивал: — А ты написал тест? Если написал — сиди ровно. И в 95% случаев он оказывался прав: баги находились где угодно, но только не на бекенде. Много лет спустя я запускал другой проект, в котором пирамиду тестирования мы построили изначально. Приготовились к двум ночам дебага, настроили связи между микросервисами, дёрнули рубильник… и оно просто заработало. Коллеги, которые не строили пирамид раньше, ходили растерянные по офису и не верили, что оно дышит и сегодня ночью можно спокойно спать. Мораль. Мы, конечно же, ни к чему не призываем. Каждый сам выбирает, спать ему по ночам после релиза или нет.

Из внутреннего: однажды у тимлида
Из внутреннего: однажды у тимлида