Как стать автором
Обновить
35
0
Николай Пунин @png

Пользователь

Отправить сообщение

Php он как JS, был рожден для одного, а потом стал использоваться для другого. Да, из-за этого какие-то библиотечные вещи кажутся плохо продуманными. Лично мне кажется, что php используют не для того, для чего он предназначен, в этом вся беда. В этом плане тот же Ruby выглядит более идеологически выдержанным.

Что касается разрабов и мест работы. Мне близка мысль про то, что везде оно одно и тоже примерно. Есть хорошие специалисты, а есть весьма странные личности.
Лет 10 назад процент этих странных личностей в php зашкаливал, т.к. для php очень низкий порог входа, чтобы потом считать себя разработчиком.
Однако сейчас положение дел немного поменялось. С появлением всяких java-курсов и течения "войти в ИТ", появилось куча java-истов, которые ну немного до разраба не дотягивают. Можно тоже самое сейчас сказать про java, внятный хорошо сделанный проект с хорошей командой(ну то есть хорошее место работы) нужно ещё поискать. Про интервьюверов вообще молчу...

Комментарии уже закрыты, а хотел сказать спасибо за статью. Плюсанул в карму :)

в этом месяце получил похожую проблему.

был у меня монитор AOC 27'' 4K, подключал к ноуту HP ProBook 4G. Ноут 2019-ого года. у него есть порты type-c и hdmi (какой версии hdmi - я не нашел внятного описания ни где).

Работало всё прекрасно на 4K@30Гц.

Год жил с этим монитором, потом он сломался, я его сдал а вместо него взял другой. выбор пал на asus gaming VG289Q1A 28'' 4K. Приехал монитор, а подключаю его через HDMI, а максимальное разрешение не ставится. Оказалось монитор не поддерживает частоту в 30Гц. только 50 или 60. Внезапно. Неожиданно и обидно. Купил дорогую железку, а она "не работает". В итоге, принял решение, сдать монитор обратно в магазин, а вместо него взять AOC U27P2CA 28'' 4K. У него всё есть, в том числе type-c. Планирую подключать к ноуту через него. И то, я до конца не уверен, что я воткну всё в ноут и всё заведется.

Ковырялся в спеках современных 4K мониторов, везде стоит 60. Список поддерживаемых режимов нашел только для мониторов asus. У остальных просто страничка на сайте.

И проблема есть, производители мало что пишут в описании, что-то более детальное не доступно, и в этом беда.

За статью большое спасибо. Всё очень четко.

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

Это попытка разработчика загнать ВСЁ в параметризированные кейзы. Точнее в один параметризованный тест. Это приводит к тому, что этот параметризированный тест всё чаще становится всё крупнее и сложнее (к тому же для некоторых кейзов делает что-то лишнее).

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

Интересная статья, где-то узнал себя :) Мысли вслух, по этому поводу.

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

Путей разрешения несколько, вариант первый — и самый логичный, искать другую команду, а не воспитывать эту. Работать надо единомышленниками, которые считают, что нормально — это убить 1.5 дня на рефакторинг перед выполнением задачи, которые перед комитом смотрят warring-и компилятора, у которых стоит плагин для sonarCube, смотрит цикломатическую сложность кода и не дает комитить явную фигню.
Должен быть devops — и внятное CI, отчеты sonarCube и кодопрокрытия тестами. Развиваться лучше в рамках такой команды.

Можно в текущей команде заработать авторитет и сделать так, чтобы тебя слышали и уже всё выше перечисленное внедрить здесь и сейчас, но не каждый проект даст с собой такое сделать в силу объективных по бизнесу причин. Но это тот ещё путь самурая. Я был в командах, в которых тесты писал я один, остальные фигачили как придется.

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

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

Такое лучше через assert не реализовывать. Лучше правда такое делать так, как описано в #comment_8207963
Мне такой вариант нравится больше, чем assert. Хотя там над API нужно серьезно думать.
Но всё же, я больше склоняюсь к мысли, что всё это не нужно.

По мне лучше делать так:

1. Явные проверки закрыть UnitTest-ами.
2. Входные данные отбраковывать через throw new IllegalState или какими-нибудь чеками из guava (там их мало, мне пришлось дописывать свои, но в том же ключе).
3. И в тестовой среде, и production код должен работать одинаково.
4. Идти по пути максимальной понятности кода.

Таким образом, мы коду задаем жесткое API и уже заранее знаем что может произойти, и как это обработать. Если всё сделать правильно, то лишние assert не особо нужны. Действительно, зачем они нужны, если на любое некорректное поведение в системе мы получаем Runtime.

Кроме, того это замечательно ложится на EJB, в которых транзакции автоматом откатываются при Runtime.

Далее, мне сложно понять, почему это проверки могут так сильно тормозить, мы же не архиваторы пишем. Чаще упираешься в базу (или в алгоритмические ошибки), а не в лишнее сравнение. Мне кажется в большинстве случаев это стрельба из пушки по воробьям и кустарная оптимизация. Толку от нее мало, зато сложностей туча. Например, утащили мы класс во время рефакторинга в другой пакет, и получили, что assert не запускаются. По мне, это лишние контракты в коде.
Про мусор в коде, уже писали. Ведь это фактически мертвый код.

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

Почитал ветку комментария #comment_8208035. Полностью согласен с вашими оппонентами. Особенно красноречив последний комментарий. Я тоже так делаю. Idea рулит!
Коллеги, по самой статье есть ряд замечаний и фактических ошибок.

По содержанию, толком не описано зачем же нужны assert и когда их использовать стоит, а когда не стоит. какие есть достоинства и недостатки.
Если этого нет, то это просто частичный копипаст документации.
Статьи про эту тему на харбе уже были(например, вот этот вариант более информативен). Что нового дает именно ваша статья?

По примеру кода полно фактических ошибок использования assert:

1.
assert initReferenceSet();

В assert никогда нельзя вставлять вызовы функций. эти функции могут менять внутреннее состояние программы. В вашей ситуации получите, что с выключенным assert initRederenceSet никогда не выполнится, т.е. получите багу на production, которая не повторится на тестовой среде (я предполагаю, что в production они выключены, т.к. нафига они там нужны — это отладочный функционал).

2.
assert addToReferenceSet(e);
//....
assert removeFromReferenceSet(o);

Проблемs такие же, что и в пункте 1.
3.
assert referenceSet.size() == size() :
                "Cool size diverged from reference size";

А это вообще ворох проблем. К пункту 1 добавляется возможный невнятный NullPounter в режиме дебага, которого не будет на production.

Всё же, желательно, чтобы код с включенными assert и без них работал и работал одинаково.

Теперь о проблемах assert.
1. Народ правильно писал выше. На production они не нужны, т.к. не хорошо, когда приложение разваливается на некорректных данных. Обрабатывать эти assert не удобно. Об этом уже писали, не буду повторяться.
2. throw new IllegalStateException во всех отношениях лучше. Об этом тоже писали.
3. Они действительно захламляют код, и при определенной неаккуратности, его ещё и ломают.

Плюс у assert только один, они в ядре java, их можно включать и выключать только для определенных пакетов или же целиком. Т.е. это не плохая отладочная штука, но при условии, что умеешь ей пользоваться и знаешь о возможных подводных камнях.

я могу поработать из дома, если приболел :)
Но дома работать сложно, обстановка что-ли не та )
Хорошие рубисты тоже стоят не дешево
да контракт. всё правильно.
в добавление к первому пункту.
я часто использую аннотации в inner-классах. Тогда вся логика в одном месте и всё понятно.
Но это не бизнес логика, это вспомогательные фичи на отображение данных
я тоже согласен!
Сейчас правлю большой проект (~ 10000 классов). и там рефлекшен. Отлаживать это — просто ад. Ходишь по коду при помощи полнотекстового поиска. и по другому никак.

добавлю свои мысли:

1. между интерфейсом и аннотациями должен быть баланс. Взаимодействие двух модулей — это обычно интерфейс. Реже аннотации в классе, чтобы не плодить не нужную иерархию интерфейсов
2. нельзя, понимаете, нельзя делать на аннотация что-то большое и сложное. Часто люди увлекаются и делают монстра с полу-динамическим кодом. Для больших проектов — это большое зло, там уследить за всем практически сложно, помогает статический анализ, а рефлекшен убивает статику.

попробуйте JRebel.
чем вам не нравится вариант 3?

если речь идет о С++, то это может быть наследование от нескольких интерфейсов.
ведь в С++ нет интерфейсов, там только классы
буча читал.
класс — это тип объекта.
есть понятие инкапсюляции. мега важное, оно определяет объект, как сущность определенного единого поведения. Иногда для поведения нужны ещё и данные, но не обязательно.
описал ниже.
Насколько я понял, в статье активно предлагаются вариант 1 и вариант 2.

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

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

Надо всё это описать, отрендерить красиво и тому подобное…

проектируем
1 вариант
заводим базовый класс машина, по матрешке нагручиваем наследование, куда кладем конкретные реализации.
Если классов мало, то вроде как так можно делать, но количество разных комбинаций растет лавинообразно. С этим нужно что-то делать!

Для машин так же может быть какая-то иерархия, которая будет мешаться нашей. Это вторая проблема.

2 вариант
вводим класс машина, а в него кидаем кучу подобъектов:
характеристики марки, физика и тому подобное
Фактически мы активно использовали делегирование
У характеристик создаем параллельные иерархии. Получаем фактически патерн стратегия.

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

3 вариант
часть характеристик, необходимых для управления, живут в объекте машина.
часть характеристик, необходимых для реализации, живут в объекте реализация машины.
получается мост в примитиве. А если для машин сделаем свои иерархии, то получится прямо настоящий мост.

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

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

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

вроде как ничего не упустил.
Тут всё сложнее.
Не хочется применять мост, не нужно, тут в рамки никто никого не загоняет.
На применение моста есть свои ограничения.
ИХМО, это один из самых сложных партенов.
в Том же GoF прописано зачем они это делают и когда имеет смысл делать это, а когда не стоит.

Разделение моста — не является нарушением принципа ответственности.
у верней иерархии ответственность крупной абстракции

у нижней — ответственность реализации (которых может быть много)
не нарушается. в мосте у каждой иерархии своя ответственность.

Информация

В рейтинге
Не участвует
Откуда
Тамбов, Тамбовская обл., Россия
Дата рождения
Зарегистрирован
Активность