Здравствуйте, Sheridan, Вы писали:
S>А что мешает то сделать второй шаг и поддерживать свежие версии либ для проектов? Тогда и докер не нужен то будет.
Это не бизнес требование. Это не всегда нужно, не всегда целесообразно и, часто, вредит. Уже 100 раз написали про эту твою религиозную догму.
В реальной жизни это не применяется, что доказывает, что в реальных проектах тебя нет и самозвание словом "специалист" — абсурдно и смехотворно.
Естественно, разжевывать почему это так — выгодно только когда применяется для неопытных и перспективных людей, которые научатся и будут приносить прибыль. Тратить время на самозванцев — слишком большая честь.
Здравствуйте, Sinclair, Вы писали:
S>Уж очень мало остаётся задач, в которых удобно описывать решения в терминах объектов-с-состоянием, и обмена сообщениями.
Мир сместился с сторону data-driven и реактивность из-за больших потоков данных, раньше такого не было просто.
Здравствуйте, Hobbes, Вы писали:
H>Я в последнее время придерживаюсь точки зрения, что наследование должно было Интерфейс — [0..N] Абстрактных классов — Имплементация. Если родительский класс не абстрактный, то поведение наследника должно чем-то отличаться от поведения родителя, иначе не нужно было бы существование наследника. А полиморфизм, при котором поведение наследника отличается от поведения родителя, я считаю антипаттерном.
У тебя здесь противоречие
1. ты заявляешь, что должен быть интерфейc-абстрактыйкласс-реализация. Ни для чего больше не нужно заводить этот интерфейс, кроме как абстрагирование. И с абстрактным классом ровно то же.
2. Ты утверждаешь, что поведение наследника должно чем отличаться родительского
3. при этом, если поведение наследника отличается от поведения родителя у тебя это антипаттерн
Зачем тогда огород городить?
Итого — п1 это уже заявка на полиморфизм, т.к. через один интерфейс сможем работать сразу со всеми наследниками. А в п3 выясняем, что это антипаттерн
Собственно, наследование и полиморфизм это две стороны одной монеты. Все это само по себе не нужно. А цель этих приседаний — обеспечение абстракции. При помощи наследования конструируем новую разновидность, при помощи полиморфизма вызываем. Но цель — абстракция.
I>У тебя здесь противоречие I>1. ты заявляешь, что должен быть интерфейc-абстрактыйкласс-реализация. Ни для чего больше не нужно заводить этот интерфейс, кроме как абстрагирование. И с абстрактным классом ровно то же. I>2. Ты утверждаешь, что поведение наследника должно чем отличаться родительского I>3. при этом, если поведение наследника отличается от поведения родителя у тебя это антипаттерн
I>Зачем тогда огород городить?
I>Итого — п1 это уже заявка на полиморфизм, т.к. через один интерфейс сможем работать сразу со всеми наследниками. А в п3 выясняем, что это антипаттерн
Значит я не совсем понятно донёс свою мысль. Не должно быть такого, чтобы можно было создать объект родительского класса и объект производного класса. Т. к. если у них одинаковое поведение — то непонятно, зачем нужны разные классы с одинаковым поведением. А если поведение разное, то получается, что объект производного класса не может быть использован вместо объекта родительского класса, что я считаю антипаттерном.
Интерфейс отличается от неабстрактного класса: от интерфейса ожидается полиморфное поведение, а от неабстрактного класса нет.
H> А полиморфизм, при котором поведение наследника отличается от поведения родителя, я считаю антипаттерном.
Ты проявляещь ту же узость сознания, что и Барбара. Наследование — это не только наследование интерфейса. Но и в более широком смысле результат применения другого принципа — повторного использования кода. Отсюда появляется, например, private наследование (когда никакой интерфейс не может наследоваться).
Но, да, с таким подходом собеседование не пройдешь. SOLID нарушить нельзя, на заморочки собеседующего тем более наступать нельзя — короче, "Мы вам перезвоним".
Здравствуйте, Reset, Вы писали:
R>Ты проявляещь ту же узость сознания, что и Барбара. Наследование — это не только наследование интерфейса. Но и в более широком смысле результат применения другого принципа — повторного использования кода. Отсюда появляется, например, private наследование (когда никакой интерфейс не может наследоваться).
В какой ситуации private наследование лучше private поля класса?
Здравствуйте, Hobbes, Вы писали:
H>А если поведение разное, то получается, что объект производного класса не может быть использован вместо объекта родительского класса, что я считаю антипаттерном.
Наоборот, это нормально, но только в определенных рамках. Т.е. когда сохраняется контракт, предусловия, постусловия и тд. Как только это ломается, например метод Add по факту начинает удалять, это конечно же паскудство.
Здравствуйте, Sheridan, Вы писали:
C>>Наследование классов — оказалось противопоказано и в классических ООП, так как создаёт слишком сильную связность. А детальный контроль доступа просто не нужен, достаточно разделения между публичным интерфейсом и приватным для пакета. S>Чем protected то не угодил?
Тем, что оно работает только для наследования классов (реализаций). А это уже однозначное зло.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Ночной Смотрящий, Вы писали: НС>>Абсолютно. S>Вот я всё больше начинаю к той же точке зрения склоняться. S>Несмотря на то, что всю жизнь (с 10 класса) писал на языках с ООП, и привык мыслить именно им.
S>Уж очень мало остаётся задач, в которых удобно описывать решения в терминах объектов-с-состоянием, и обмена сообщениями.
А не надо мыслить в рамках одной парадигмы. Неимоверно рулит мультипарадигменность, когда для части задач применяется ООП, для части ФП, для части процедурщина, для части декларативность. Современные языки идут в эту сторону. И язык, который заточен только под одну парадигму уже будет достаточно убог и не универсален.
Здравствуйте, Ikemefula, Вы писали:
I>Наоборот, это нормально, но только в определенных рамках. Т.е. когда сохраняется контракт, предусловия, постусловия и тд. Как только это ломается, например метод Add по факту начинает удалять, это конечно же паскудство.
Контракт может сохраняться, я не спорю. Но зачем делать так:
Interface --> Impl1 --> Impl2
Когда логичнее так:
Interface --> Impl1
+-> Impl2
А общие данные и методы можно вынести в общего абстрактного предка. Или отдельно в общего мембера.
У первого варианта в том, что объект типа Impl2 является также объектом типа Impl1, который с точки зрения функциональности, как правило, не ведёт себя как объект типа Impl1. Например Impl1 рисует на экране белым цветом по чёрному, а Impl2 чёрным по белому. А интерфейс и инварианты могут быть при этом одинаковые.
Я не рассматриваю случаи, когда Impl2 делает совсем то же самое, что и Impl1, но скажем оптимизирован для более узкого круга задач.
Здравствуйте, Hobbes, Вы писали:
H>А общие данные и методы можно вынести в общего абстрактного предка. Или отдельно в общего мембера.
Не должно быть общих методов. Если есть общая функциональность — вынести её в отдельный класс и использовать композицию.
Здравствуйте, ononim, Вы писали:
C>>Из однозначно плохих библиотек в стандартной упаковке — только SQL и log. O>flag еще абы что
Он просто сильно ограниченный, это нормально. А вот что они курили, когда не сделали log интерфейсом — вопрос.
Небольшой комментарий совсем не по теме. Но не могу не отметиться, т.к. глаз зацепился за фразу:
S>То есть в мс-архитектуре вся система и состоит из "модулей-плагинов". Те же самые идеи, что и в компонентной архитектуре, популярной 30 лет назад, только механика взаимодействия теперь построена не на RPC или CORBA, а на HTTP.
Нюанс в том, что в данный момент основным подходом снова становится RPC. Правда теперь это уже RPC поверх HTTP/2 (gRPC), но это не суть (тут https играет роль не сильно большую, чем tcp, ip, ethernet). )))
B>>почему для того чтобы соединиться с хостом мне нужно вызывать метод Dial? C>Потому, что "connect" слишком перегружен. Надо было имя придумать.
это как? мне кажется это как раз dial не соответствует тому что происходит на самом деле
B>>где мои monotonic clocks? почему вместо этого time.Now() возвращает объект, который содержит две метки времени и пытается быть умным при вычислении интервалов? C>Эрм... time.Now() всегда содержит монотонное время. Как раз очень остроумное решение. Такая вот последовательно гарантированно работает даже при изменении системного времени: C>
я согласен, что это остроумное решение, которое тем не менее, работает не всегда так как надо, иногда нужно иметь возможность просто получить одну метку времени и все
ну скажем я сериализовал две метки времени, до сервиализации между ними одна разница, после десериализации — другая
C>Это не так. string в Go может содержать произвольный набор байт.
тем не менее это не отменяет того, что path это просто строка в Go, это не deal breaker, но немного ебобо
Здравствуйте, bitboi, Вы писали:
B>>>почему для того чтобы соединиться с хостом мне нужно вызывать метод Dial? C>>Потому, что "connect" слишком перегружен. Надо было имя придумать. B>это как? мне кажется это как раз dial не соответствует тому что происходит на самом деле
Почему же? Оно "набирает" номер другой стороны.
B>я согласен, что это остроумное решение, которое тем не менее, работает не всегда так как надо, иногда нужно иметь возможность просто получить одну метку времени и все B>ну скажем я сериализовал две метки времени, до сервиализации между ними одна разница, после десериализации — другая
Это практически единственный пример, где оно не работает. Но если очень хочется — берём и вызываем clock_gettime напрямую.
C>>Это не так. string в Go может содержать произвольный набор байт. B>тем не менее это не отменяет того, что path это просто строка в Go, это не deal breaker, но немного ебобо
Ну они могли бы ввести тип "type Path string", но смысл? Массив байт неудобен из-за того, что нельзя гарантировать иммутабельность.
Здравствуйте, alex_public, Вы писали: _>Нюанс в том, что в данный момент основным подходом снова становится RPC. Правда теперь это уже RPC поверх HTTP/2 (gRPC), но это не суть (тут https играет роль не сильно большую, чем tcp, ip, ethernet). )))
Интересно, с чем это связано. Что именно компенсирует недостатки RPC по сравнению с REST?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали:
C>Почему же? Оно "набирает" номер другой стороны.
ну типа мы набираем номер другой стороны и ждем когда нас соединят, получается что dial это только первая часть процесса
плюс у меня еще ассоциации с signalling в VoIP появляются
C>Это практически единственный пример, где оно не работает. Но если очень хочется — берём и вызываем clock_gettime напрямую.
мне кажется можно придумать еще, но главное конечно, это то что теряется аспект документирования кода и интерфейсов
скажем если я вижу где-то в интерфейсе duration и это системное время, либо наоборот монотонное, я что-то сразу понимаю про то как это все должно работать, а тут нет, мелочь конечно, но неприятно
C>Ну они могли бы ввести тип "type Path string", но смысл? Массив байт неудобен из-за того, что нельзя гарантировать иммутабельность.
жить с этим конечно можно, но опять же, вот есть у меня ф-я, которая преобразует путь в каноничный (в Go такой ф-ии почему-то нет, но представим что есть)
так вот, ф-я получает на вход путь в виде строки? при этом она не делает то что можно подумать (преобразует строку используя только входные данные), она лезет в ФС и делает что-то сложное, использует системный вызов, который может делать какой-то ввод-вывод и тд, но ф-я выглядит так, словно она просто преобразует строку
в общем, мое мнение — strong types это хорошо, в плюсах к этому уже давно пришли, там уже принято вводить именованные типы вместо фундаментальных, там где это имеет смысл