Как стать автором
Обновить
18
0

«и швец и жнец...»

Отправить сообщение
Это был «Черный свет» Виктора Мелентьева.

Виталия Мелентьева
Есть такой способ, и даже не один. Я использовал и bfg-repo-cleaner (сторонний) и git filter-branch (нативный). Первый быстрее.

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

Neveil вот, например, статья, которая могла бы послужить мотивацией: habr.com/ru/post/470097
Генерацией текста ошибки управлять можно. За это отвечает поле «formatError» в структуре конфигурации обработки запроса, используемой в graphqlHTTP(...). Можно также вставлять свои поля. Вот пример из работающего кода. Правда, используется не Apollo, a graphql и express-graphql.

app.use('/api', auth.validateTokenMiddleware, graphqlHTTP((req, res) => {
___ return {
___ ___ schema: apiModulesManager.gqlSchema,
___ ___ pretty: true,
___ ___ context: { req, res, dataloaders: buildDataloaders() },
___ ___ formatError
___ };
}));

function formatError(err) {
___ log.error(err);
___ return {
___ ___ // standard fields:
___ ___ message: err.message,
___ ___ path: err.path,
___ ___ locations: err.locations,

___ ___ // extended fields:
___ ___ code: err.code || 'not classified error',
___ ___ localizedMessage: err.locMessage || `not localized: ${err.message}`
___ };
}


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

P.S. Отступы в коде были безжалостно пожраны хабром. Пришлось извращаться с "___ " :(

P.P.S. Естественно, речь идёт об ошибках, полученных во время выполнения функциональной части запроса, а не при парсинге текста запроса (то бишь синтаксических ошибках в тексте запроса).
Chessman97, посмотрите ещё в сторону GraphQL. Мы были и до сих пор остаёмся весьма довольными, перейдя на него с REST API.
Очень часто основной приобретаемый навык за N лет работы — желание выдавать субъективное за объективное ввиду попытки оправдать важность этого опыта.

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

Кстати, заголовок статьи прямым текстом говорит о том, что статья субъективна. Или у меня с Вами разные определения понятий субъективного и объективного?

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

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

Альтернативы, как я понимаю, должен видеть сам читатель. Опять же, читателю стоит понимать, что абсолютной истины не существует, что всегда есть исключения,… Зачем об этом вообще упоминать в контексте «чему Я научился»?

Вы видите, что должны быть альтернативы и исключения — Вы молодéц! Вы относитесь к целевой аудитории! Кстати, если Вы понимаете, что «нигде нет ни альтернатив, ни исключений, а во многих [тезисах] они должны были быть и в немалом количестве», (без сарказма) почему бы Вам о них не написать статью?
Вдогонку. Неправильно понял про статистику. Общая статистика работы программы, это штука ортогональная по отношению к основной функциональности. Если средства языка позволяют её подключить ортогонально, например через аспекты, то всё здорово. А если нет, приходится исхитряться. Как-то писали генерирование прозрачных врапперов (proxy), сложенных в отдельные загружаемые библиотеки. При загрузке, либо использовались оригинальные библиотеки, и статистики не было, либо библиотеки со сгенерированными врапперами, которые догружали оригинальные библиотеки, тогда статистика была.

То есть, и тут наличие «и» в имени (tryLockAndSaveStatistics), помогает увидеть ортогональную функциональность и задуматься о том, как бы её задействовать «прозрачно» по отношению к главной функциональности.
Я не согласен с утверждением автора, что отладчики «просто не оказывают той помощи, которой от них многие ждут»

Да, по этому поводу автор сказал немного. Я экстраполирую его предыдущий абзац, добавляю свои ожидания помощи от отладчиков N лет назад, сегодняшние ожидания многих коллег, и соглашаюсь с утверждением. Но не берусь утверждать, что Вы неправы ;)
Я воспринимаю сказанное автором следующим образом. Если именно в названии функции присутствует И, то тут, скорей всего, что-то не так. Функция с «хорошим» именем (без «и») функция при этом может делать несколько взаимосвязанных вещей, если это действие можно воспринимать… атомарно, что-ли. Понятно, что функция readFile должна и открыть файл, и прочитать его, и закрыть его. При этом у нас не возникает желания назвать такую функцию openFileAndReadItAndCloseIt.

Точно так же с tryLock. К стати, я бы описал то, что она делает, несколько отлично от Вашего варианта. А именно: пробует захватить (залочить) мутекс. В случае успеха возвращает true, при неудаче возвращает false. Но это всё ерунда, в названии-то «and» не стоит ;)

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

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


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

В целом, я вижу в этом не догму, а хороший способ проверки на вшивость своего кода. Опять же, разумные исключения/расширения в моём мире имеют право на жизнь. Скажем, в некоторых ситуациях может быть оправдано существование f1, f2 и f1ThenF2. Естественно, f1ThenF2 должна быть реализована посредством вызовов f1 и f2, а не, скажем, копированием и вставкой их тел, или, что ещё хуже, написанием кода «с нуля». Хотя и тут тоже могут быть исключения ;)

В общем, по-моему, нужно понимать, с какими именно проблемами боролся автор, и делал соответствующие «записки на манжетах». Так же нужно понимать, что записка эта справедлива для определённого контекста. Да, в 80% или в 90% случаев контекст именно этот. Но вот оставшиеся 10%… Короче, проповедую подход без фанатизма :)
Думать на будущее означает тратить силы впустую

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


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

Не далее как две недели назад, во время очередного рефакторинга, выкидывал из API кусок кода с нетривиальной логикой, который ни разу не использовался и в планах на использование не стоял. К сожалению, начал это подозревать уже после процесса «въезжания» и рефакторинга этого куска. Коллега сказал, что разработал его «для единообразия». Причём это я отношу лишь к «думанью на недалёкое будущее»…

Не используйте булевы значения в качестве параметров.…

Для этого существуют enum-ы.


Так не о enum-ах же речь. Для этого существуют много разных способов, например, описанные автором.

Я встречал данный антипаттерн в ситуациях, когда поведение процедуры следовало изменить при определённых внешних условиях. Тогда список параметров расширялся, добавлялся N+1-ый параметр типа boolean со значением по умолчанию false. Этот параметр «включал» новое поведение. Таким образом, считалось, что весь старый код продолжал работать как раньше, а там, где требовалась изменённое поведение, вызывалась процедура с этим параметром true. Мне, например, весьма часто не было понятно, что-же этот последний true обозначает…

А так — да, enum-ы — хорошая штука.

«Правильный инструмент для задачи» — это способ навязать своё мнение

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


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

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

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

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

ВСЕГДА используйте в датах часовые пояса

ВСЕГДА используйте UTC, кроме пользовательского ввода-вывода. Если с часовыми поясами работать всё-таки придётся, убедитесь, что в используемой библиотеке достаточно мало багов (от стандартных библиотек часто приходится отказываться).


«Дата с часовым поясом» — это больше, чем UTC. По ней можно сказать, например, когда у человека день, а когда ночь. Стоит ли ждать от него скорого ответа. Стоит ли ему сейчас звонить…

Я наблюдал и участвовал в задачах перевода систем с локального времени без часового пояса на UTC и иногда потом на время с часовым поясом. В другую сторону перехода делать, по крайней мере в моём мире, никогда не требовалось. А как бы было хорошо, если бы c самого начала время просто было с часовым поясом!

Поэтому Ваш совет «ВСЕГДА используйте UTC» я рассматриваю как шаг назад по сравнению с тем, что предлагает автор. Да, если используемые библиотеки с часовыми поясами работать не умеют, ничего не остаётся, как взять только UTC. Но это для меня безысходность, а не практика, которую я бы всем предлагал.

Отладчики переоценены

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


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

Речь-то идёт о том, что будет делать разработчик, когда воспользоваться отладчиком нет возможности. Тогда-то и будет польза в умении работать без отладчика, в грамотном логировании,… etc.

Оптимизации оставьте компиляторам

Только микрооптимизации. Если вместо дерева или хеш-таблицы вы возьмёте простой массив, скорость программы может упасть в миллион раз, и никакой компилятор вам тут не поможет.


Тут тоже для меня не всё так просто. «Если вместо дерева или хеш-таблицы вы возьмёте простой массив...» — Ваш пример я отношу к ошибкам проектирования или ошибкам при выборе структур данных. И, соответственно, то, что вы назвали «оптимизацией» для меня является процессом исправления ошибки.

Я бы сказал, что улучшениями алгоритмов стоит заниматься, как тó: замена используемых структур данных на более подходящие для Ваших условий, добавление кэширования,… etc. Впрочем, именно так я и понимаю слова автора: «О чём вам нужно думать, так это… о том, как улучшить текущий код.».

Опять же, компилятор делает как «микрооптимизации» (вынесение переменных из тела цикла, автоматическое принятие решений о том, какие переменные должны быть регистровыми,… etc.), так и «макрооптимизации» (использование интринсиков, раскрутка хвостовой рекурсии, инлайнингом часто выполняемых методов...)

Соответственно, зная об этих оптимизациях, я стараюсь писать красивый хороший понятный код.

Кодекс поведения защищает вас, а не их

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


Для меня привычнее «в чужой монастырь со своим уставом не лезут».

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

Не буду спорить о значении приведённой Вами пословицы. С моей точки зрения она к описанной ситуации подходит не лучшим образом.

Кто-то скажет: «Может, если ты поговоришь с этими людьми, они перестанут так делать?» Я считаю, что не перестанут.

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


Автор публикует личное мнение, основанное на довольно продолжительном опыте. У Вас другое мнение. Это не означает, ни что Ваше мнение, ни что мнение автора ошибочны.

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

Со всеми пунктами согласен, по крайней мере понимаю, какую мысль хотел донести автор, и на какие грабли он наступал.

Уф, как-то длинно получилось. Просто за душу взяло… :)
Полностью с Вами согласен, производительность фронтенда зависит также от бекенда. В то же время, читая заголовок статьи и саму статью, я склоняюсь к мнению, что автор поставил перед собой цель, описать изменения именно во фронтенде, которые позволяют повысить его производительность.

Опять же, даже при вылизанном бекенде, во фронтенде «развернуться» можно о-го-го как. Так что весьма полезно знать, что же делать стоит, а что нет. Из памяти не выходит случай, когда на фронтенде по разным критериям самостоятельно сортировалась таблица идентификаторов за O(n**2). Данные при этом «кэшировались» в неотсортированом массиве. Сложность операции O(n**3) начинала достаточно быстро ощущаться при увеличении n. Вишенка на торте: в таблице могло оказаться больше элементов, чем допускал кэш.

Ещё нам часто приходится писать фронтенд, используя бекенд сторонних фирм, которые вообще никак не реагируют на просьбы оптимизировать его в конкретных местах. Так что нам остаётся ограничиваться только оптимизацией фронтенда, хотя мы и представляем себе, насколько удобнее и зачастую эффективнее профилировать бекенд.
MarazmDed «Решето Эратосфена» — это, если я правильно помню, алгоритм, который выщитывает простые числа в диапазоне от 2 до N путём вычёркивания в этом диапазоне всех чисел, больше текущего простого числа, которые делятся на это число. Мы начинаем с 2. Следующим простым числом будет первое невычеркнутое число. Так что, сам алгоритм предписывает сохранять информацию о том, «вычеркнуто» данное число или нет, для чисел в диапазоне 2,…, N.

Бесспорно, информацию можно хранить по-разному. Например, сделав утверждение, что поскольку все чётные числа непростые, мы всегда расматриваем только нечётные. Таким образом массив уменьшается в два раза…

Вы, судя по всему, предлагаете хранить только простые числа в двоичном дереве. А как же непростые? Как алгоритм будет «вычёркивать» соответствующие числа больше текущего? Или Вы, всё-же, предлагаете хранить информацию о том, вычеркнуто число или нет, для чисел от 2 до N в двоичном дереве? Тогда это скорее не оптимизация, а совсем даже наоборот…
Спасибо за интересную статью. По теме есть очень хорошая классическая статья под авторством Jeremy Manson и Brian Goetz, сжато и по-возможности несложно описывающая JMM: JSR 133 (Java Memory Model) FAQ. На Хабре проскакивал перевод.
Понял. Спасибо, внёс изменения.
Проблема воспроизведения окружения возникает не только в production, но и в development, да и в любой другой сборке. Другими словами, я бы оставил всё как есть — не забываем класть в git. Независимо от типа сборки. Или я Вас неправильно понял?
О том, на какие базовые вещи стоило бы нашей команде обратить внимание, чтобы избежать проблем с работой программ.

Работа над ошибками, одним словом. Ошибки были найдены, проанализированы, исправлены. Базовые понятия, непонимание которых вызвало эти ошибки, были разъяснены. Этими разъяснениями я и поделился.

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

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность