All streams
Search
Write a publication
Pull to refresh
28
0

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

Send message
Ну а у меня ощущение, что вы уперлись рогом в свои представления и не слышите собеседника. Ведь только тролль может быть с вами не согласен, правда?

Я пока слышал от вас аргументацию уровня джуниора, и «особое» понимание принципов SOLID.

Из ваших слов получается:

SRP вы воспринимаете как необходимость дробить до безумия,
OCP — запрет на редактирование кода
LSP — это о преобразование сложных типов
ISP — требует интерфейсов из одного метода

Честно я ждал от вас вдумчивых аргументов, тоскуя вечерами. А получается что вы просто не понимаете, не умеете и логично что не любите SOLID и всячески защищаете свою безграмотность.
что в Java один-единственный вызов String.format("%0.2g", 0.1); порождает несколько сотен объектов


Это вопрос уже не про SRP. А по поводу кол-ва объектов — повторюсь — SRP не про то что нужно все измельчать, а про то, как делить.
Ну вот профайлер вам показывает, что создание 100к объектов вместо 10к — это как-то сильно долго. Что вы там соптимизируете, не выпиливая SRP?

Прежде чем «грязнить» код — есть много других возможностей:
1) Большинство проблем происходят из O-сложности. Если O — побеждена — переходим на уровень малой крови.
2) Делаем синглтоны или кэши для часто используемых объектов, меняем ref на value типы (если позволяет инфраструктура) — итд.
3) Если и это не помогло — то часто можно упростить или реорганизовать архитектуру во благо скорости и без ущерба смыслу (на этом этапе уже понятно как).
4) Для высоконагруженных — не забываем про горизонтальное масштабирование.

И только потом, когда все вышеперечисленное не помогло — начинаем крошить код во благо скорости. Но необходимость этого встречается редко. Как правило на мобилках и ARM. И, безусловно — тут все средства хороши.

Что самое главное — предыдущие 4 пункта сложно выполнить, если у вас там все SOLID-ы порушены вкривь и вкось.

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

Он говорит про изменение поведения, а не про то, что код нельзя трогать. Например — смена конекшн стринги из конфиг файла.

Или более сложный случай — вы хотите сменить одну SQL базу на другую — значит подготовьте бек-код так, что бы можно было менять провайдера DB, а не удалять старого и вместо него писать нового. Так же это говорит о том, что предпочитайте if-чикам — стратегии и композицию

LSP фактически утверждает, что все типы должны быть ковариантны. Что во первых не так. А во вторых даже не является свойством типа.

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

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

Не знаю, что такое «атомарные» тесты, но написать код так, чтобы он проходил один тест, но не проходил остальные, обычно сложно и бессмысленно.


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

Дьявол в слове «преждевременная». Архитектурная оптимизация должна выполняется как можно раньше, так как потом менять её будет сложно или даже невозможно. Это, кстати, большое заблуждение, что можно не думать о скорости, пока петух не клюнет.


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

Ко кровавому легаси приводит отсутствие регулярного рефакторинга. А OCP явно запрещает рефакторинг. OCP полезен лишь при взаимодействии со внешними клиентами, когда нужно сохранять обратную совместимость.


Ocp не запрещает и не поощряет рефакторинг. Он говорит что «изменение поведения кода нужно делать через… поведения-)». Иными словами — не надо хардкодить.

Не, вы не поняли суть проблемы. Смотрите, Cat является подтипом Animal, Cat[] является подтипом Animal[]. И если мы только читаем, то мы можем где угодно вместо Animal[] передать Cat[]. Но если мы где-то помещаем в массив, например, Dog, то, внезапно, мы уже не можем передавать Cat[] вместо Animal[]. Во времена Барбары об этой проблеме ещё не думали.


Либо я вас по прежнему не понял, либо вы путаете LSP и проблемы ковариантных/контравариантных преобразований и структурной типизации.
TDD. Про TDD в оригинальном варианте максималиста — я соглашусь с вами. Однако гармоничный путь, описанный в исскустве автономного тестирования — это смесь написания тестов иногда перед, иногда после, но в основном — одновременно с написанием кода. «думай о тестах и коде как о едином целом (с) Тестиус». Потому я и указал TDrivenD/TLastD что бы не нарваться на формализм. Кстати отсутствие атомарных тестов зачастую приводит к кровавому легаси.

SRP. Проблема в понимании SRP как «дроби пока дробится». Но это не так. SRP — он же принцип единой изменчивости, единой ответственности и локализации фичей — говорит про границы декомпозиции, а не про ее размер. Нарушение Srp — это не только God-object, но и размазывание и дублирование по коду какой-то конкретной фичи. Дублирование кода, как вы понимаете отнють не ускоряет даже MVP. Ежели мы касаемся вопросов оптимизации — то «преждевременная оптимизация — зло (с)». Кстати неверная декомпозиция, приводит к костылям в коде и кровавому легаси.

OCP, при нормальном проектировании необходим для выполнения SRP и тестирования. А устаревшие интерфейсы можно просто удалить. Другое дело что вы не сможете их удалить если у вас нарушен OCP, что приведет вас к кровавому легаси.

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

ISP не приводит к интерфейсам из одного метода. Аналогично SRP, ISP говорит о том как нужно делать интерфейсы в спорной ситуации, и позволяет развязать жуткие клубки зависимостей. Это крайне необходимо для больших команд, сложной бизнесс логики и ограниченных контекстов. В противном случае — ну вы поняли ;)

DIP — соглашусь. Есть доказательства того, что слепое следование DIP приводит к рекурсивному генерированию кода. Таким образом DIP это не принцип, а ползунок, пренебрегать которым не стоит ни в одну, ни в другую сторону.
Приведите пример, я видел крайне мало удачных иерархий, и крайне много удачных композиций.
Из очевидного — Tdd/Tld с покрытием в зависимости от задач и SOLID. Начинайте.
В синтаксическом дереве — набор типов фиксирован стандартом языка.

С другой стороны Visitor это не только паттерн матчинг но и SRP точка. Как раз та самая логическая группировка процедур обработки узлов.

И в довесок к ништякам — Visitor есть очень удобный интерфейс для использования в DFS. Тоесть отлично разделяются алгоритм обхода дерева и алгоритм преобразования.

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

Итого. В данном случае, визитор это:
— SRP
— Читабельность
— Строгая типизация

То есть больше, чем просто паттерн матчинг фиксированной иерархии в одном модуле.
Я не очень опытный разрабочик компиляторов, но, кажется для конкретно вашей задачи отлично подходит «Визитор». Безусловно нужно смотреть контекст задачи.

С проблемой каши из кода, при подходе DFS по синтаксическим нодам со свитчами и процедурами я столкнулся уже при N = 7, и M = 30.

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

Один такой визитор будет инкапсулировать один из N алгоритмов для всех M нод. В случае дубляжа кода можно воспользоваться как полиморфизмом так и наследованием.

Но если вы не учились у Дейкстры, то поймете все превратно. Ведь они то учились у него.
Я не использую плохие подходы, и все ок. ЧЯДНТ?
Итак. Условия задачи

Стабильность нет кора — не ниже джава стека.
Стабильность мини и микросервисной архитектуры — не зависит от того что сервисы на разных платформах
Стоимость разрабов джава — неоправданно выше.
Стоимость разработки на джава — немного выше
Скорость работы стека кора — выше

Вопрос: при выборе какой технологии для нового сервиса (Java или Net) у вас появятся основания для увольнения?
Проприетарная


То, что их недавно выложили де Юро — не сделало WCF стандартом де факто, сколь угодно интересным комьюнити или другим компаниям.

Я в свое время, забавы ради, написал свой Middleware который симулировал WCF сервис с net.tpc binding-ом


Вероятно я вам не понял — вы имеете ввиду middleware asp.net core?
Он уже не «полигонный». Дополнительной тенденцией к переводу является мини и микросервисность современных решений. Стоит один раз человеку написать модельку с 20ю свойствами на C# (после джава) и решение писать новый сервис на коре начинает вызывать теплые, интригующие и по детскому чистые эмоции.
Как хорошо что он туда не попадет. Проприетарная, тяжеловесная, с изотерическими конфигами, толи Фреймворк, толи библиотека. Да, для своего времени это было круто, но теперь есть grpc, да и то, если сможете обосновать почему не использовать http
Да, черт побери — писать велосипеды это весело! (в начале)

Information

Rating
Does not participate
Registered
Activity