Search
Write a publication
Pull to refresh
-8
0

User

Send message

Не, ну в автомобилях уже есть, дойдет очередь до самолётов. Автопилот это не ИИ.

А как делать связь многие ко многим?

Не хочется офтопить и придираться

🙂

2-мя: двумя

очень остроумно

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

и не надо коверкать мои слова - я нигде не говорил "настоящий программист"

это я и так знаю, мне интересно, как вы определили, что весь web работает "На костылях, и после долгой работы над отлавливанием багов по всему стеку " )) Я где-то говорил, что программисты не делают ошибок?

Из базы CVE.

CVE (Common Vulnerabilities and Exposures) — база данных общеизвестных уязвимостей информационной безопасности.

какое отношение она имеет к вашему утверждению по поводу работы всего web'a: "На костылях, и после долгой работы над отлавливанием багов по всему стеку" и ошибками при неправильной передаче параметров? Можете носом ткнуть?

Ну в смысле "как". На костылях, и после долгой работы над отлавливанием багов по всему стеку.

откуда это вы такую статистику взяли?

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

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

Я так понимаю, спор зашел в тупик. О чем спорить, если нет никакого реального куска кода (с F# не знаком) с реализацией и использованием подтипов.

Чистая, после trunc. Потом тестом (мы же тесты пишем?) туда добавляется два пользователя, и у каждого по картинке. Ну так как у нас ID там в обоих случаях 1 и 2, и пользователю 1 принадлежит картинка 1, то сами догадаетесь, как именно перепутанные аргументы могут пройти через сито и оказаться в проде?

Выше же написал.

Как же тогда web то работает? где выводятся куча изображений, данных пользователя, счетов и т.д. - и все это работает без ошибок и подтипов.

Потому что реализация класса ID - это примерно четыре ключевых слова и четыре скобки в Java, и три ключевых слова если лениться и взять язык с алиасами. А для функции-конвертера понадобится раза в два больше токенов, даже если единиц измерения всего две.

Сам класс маленький, его легко менять/изменять и все в одном месте. Какой подтип/подтипы вы сделаете, н-р, для денег (и 15 валют)?

Нет, не всё. Ещё по уму нужна будет конвертация из OneUnit во все оставшиеся. Но тут как раз прояснилась интересная деталь - почему-то вы думаете, будто я зачем-то предлагал на каждую новую единицу измерения длины делать новый класс. Хотя я неоднократно уже говорил, что ничего подобного не было.

Речь шла не про новый класс, а про новый тип, который нужен н-р для См. и Дм., а класс-то как раз один.

Пусть это будет микросервис на C++, с покрытием тестами на уровне порядка 60% ветвлений (для виденных мной проектов - цифра космическая, на самом деле). Ну или на Scala, с теми же характеристиками. Отладка, как водится, ручками через дебаггер.

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

В отдельных случаях у вас в функцию передаются UserID и ImageID, которые в рамках теста обе равны единице, потому что база чистая.

Или не пустой, потому что для значения uint есть и пользователь, и картинка, и что-то найдётся даже если аргументы перепутать местами. Ну подумаешь, чужие картинки кому-то показали.

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

Откуда тогда взялось 150 классов?

я такого не говорил - наоборот, нужен всего один класс на N количество разных типов.

Ну уж точно сложнее, чем реализация ImageID в лоб.

как вы это поняли?

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

в данном случае еще метод ToOneUnit() поправить в том же классе и все.

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

что за приложение и как делают его отладку?

Но при этом, деньга - это не число, а число-и-валюта. И там тоже нельзя просто взять и прибавить, если валюты отличаются.

Зависит от ситуации: если к примеру, нужно сделать наценку в 2 раза больше, то тип валюты знать не обязательно.

"ByGroupId" - это как раз предикат. Упомянутый мной Spring Data из имени методов может запросы генерировать, вот.

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

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

Безусловно - не зная код, вы ничего не сможете написать.

В отдельных случаях у вас в функцию передаются UserID и ImageID, которые в рамках теста обе равны единице, потому что база чистая. Первый запуск такое отлавливает не всегда. И даже если отлавливает запуск - это всё равно куда дольше, чем если оно просто сразу же в IDE не скомпилируется.

Вернет пустой результат. Но обычно все-таки база содержит необходимые записи, либо используются фикстуры, иначе как вы проверите работоспособность без базы?

Если именно в этом коде задействовано 150 разных видов сущностей/переменных, то скрыть их настоящий тип за всякими int и string точно разработку сделает сложнее, а не проще.

В том-то и дело, что используется несколько простых классов (https://habr.com/ru/articles/874584/comments/#comment_27813296), а не на каждый чих по новому типу переменной. Например класс MyUnit для ед. измерения, MyMoney для хранения всех валют и т.д.

Её тоже кто-то должен написать, то есть это усложняет код.

нет - она будет абсолютно простая (с элементарной логикой), где разберется даже ребенок (ссылка на несколько строк выше)

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

помимо создания нового типа, вам его еще надо как-то обрабатывать, добавлять перегрузки, менять уже существующий код и т.д., а если использовать н-р класс MyUnit, то просто добавить строку в перечисление и простой расчет в функцию ToOneUnit(), ну или IsGreater() в том же классе.

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

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

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

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

Я и не предлагаю заводить по отдельному классу - класс один.

Lengh{uint, LenghUnit} будет куда удобнее, а если его чуть более развить, но и никакого ToOneUnit не нужно, а вместо этого определить некий IsGreater, и пусть оно внутри уже само разбирается.

Ну это уже тонкости реализации, ни на что не влияющие. Можно хоть так, хоть этак, хоть оба метода использовать когда нужно.

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

Ну с ИД пользователя возможно и не имеют, а с деньгами, н-р (например), вполне могут иметь.

А ещё потому что я могу добавить ещё какой-нибудь findImagesBy(ImageGroupID id) - а вам нужно будет в названии метода перечислять все предикаты, как это в Spring Data делается, и в противном случае диспетчеризация сломается.

Перезагрузка. А если это не ИД, а ед. измерения или валюты - сколько будет таких перезагрузок?
findImagesByGroupId(uint id) - ничуть не хуже, все понятно. Какие это предикаты мне придутся перечислять?

Ну, так и запишем - в мире нет ни одного программиста. Потому что если бы это верно было, то в программах никогда не было бы багов.

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

Напротив, мы обсуждаем не "пере"-усложнение кода, а насыщение его дополнительной документацией...

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

Как это не пояснил, когда уже третье (или четвёртое?) сообщение на разные лады повторяю одно и то же пояснение?

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

Не понял, что такое н-р, но клей-то действительно нужен, особенно для сравнения 200em с 1920px - в вашем языке почти гарантированно нет возможности сравнивать такие вещи из коробки, а значит кто-то их должен был написать.

function ToOneUnit() - приведет к единым единицам.

Разработку такой подход точно упрощает, и будущую поддержку тоже.

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

Почему "Так тоже можно, да.", а не "Так лучше, да."? - в случае с классом, мы имеем легко читаемый, расширяемый и модифицируемый один тип переменной, а не 150 разных типов, 150 перегрузок, переписывание кода при изменении/добавлении ед. изм. и т.д.

А присвоение копеек к метрам как ругаться?

У вас примеры, не имеющие отношения к реальности. Никто в здравом уме, не будет сравнивать теплое с мягким. Ну а если такой найдется, то никакие подтипы/проверки/валидации уже не помогут.

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

разве не лучше:

enum UnitsMeasurement
{
    CM,
    MM,
    INCH,
    FEET,
    METER,
    // etc.
}

class MyUnit {
    uint length;
    UnitsMeasurement unit;

    public function ToOneUnit(){
      // приводим длину к любой стандартной единице
    }
}

MyUnit myUnit1 = new MyUnit(5, UnitsMeasurement.INCH);
MyUnit myUnit2 = new MyUnit(5, UnitsMeasurement.CM);

if(myUnit1.ToOneUnit() > myUnit2.ToOneUnit()){
...
}

Компактно, легко понять, легко расширить и модифицировать, аккуратная архитектура. Чем хуже подтипов?

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

Пример. Берем номер банковской карты, который как бы строка, но делаем типом. После этого анализировать "а куда мы номер карты передаем (и где он может убежать в какие-нибудь логи, в которые не положено)" - становится куда как легче.

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

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

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

LengthInch length = 5; // здесь значение в дюймах или сантиметрах?

В данном случае "наследовать от enum" и "определить enum" - это по сути одно и то же.

так зачем тогда наследовать?

Что такое let id = pow(user.id + 2, 4), и почему это должно компилироваться?

отвечу также - а почему не должно?

А почему не так:
Image? findImageBy(ImageId id)

Image[] findImagesBy(UserId userId)

а почему не так:

Image? findImageBy(uint ImageId)

Image[] findImagesBy(uint UserId)

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

программирую очень давно и не разу не приходилось искать все переменные по типу - т.е. что дает знание всех переменных определенного типа?

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

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

Можно, разумеется. Точно так же, как можно заменить большинство uint на any, выбросить тесты, сложить весь код в один файл, и тому подобное. В программировании вообще много чего можно.

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

Я уверен, что подтипы сделали не просто так и где-то они нужны, но точно не для упрощения кода, а скорее для безопасности.

Если в ЯП, на котором оно пишется, enum не относится к числам - то ImageType в принципе можно от enum унаследовать, но и это само по себе не обязательно.

Зачем наследовать, если можно сразу определить enum?

Но не в методе pow, куда этот uint можно передать, и не после операции "+ 2" .

не понял

Например, чтобы не было соблазна передать UserIdentifier в какой-нибудь Image? findImageById(uint id)

Так проще названия нормальные дать:

findImageById(uint Id) - поиск картинки по ID

findImageByUserId(uint Id) - поиск картинки по ID юзера.

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

Ну а про поиск использования любой переменной - так это есть во всех нормальных IDE (в PhpStorm & VS точно).

Ну не вижу я реального примера, чтобы прямо подтипы нужны были. И да, подтипы усложняют код и повышают безопасность (только от кого?) Неужели любой подтип нельзя заменить стандартными типами, классами, интерфейсами, структурами или перечислениями?

ImageType - это ImageType, конечно же.

и что вы будете ему присваивать? т.е. это же все равно строка, число или еще что-то.

Я не вижу здесь упрощения при любом направлении движения. Вам всё равно придётся как-то знать и помнить, что вот это конкретное значение кодирует идентификатор пользователя

ну стандартные типы данных все и так знают и помнят, в отличии от подтипов и поле uint User.Id - вполне за себя говорит, что содержит идентификатор пользователя и запоминать его вовсе не нужно, а в коде подсветит, что тип данных uint, а не какой-нибудь UserIdentifier, который может быть чем угодно.

Это, в своём роде, упрощает код за счёт ограничения возможного пространства применений для каждого значения.

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

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

Ну допустим сделал 20-30 подтипов на проект - как это упростит понимание? Например ImageType - это какой тип данных - string, int, enum или еще какой-то? т.е. мне нужно разобраться с произвольными типами данных и держать их всегда в своей голове?

В чуть более продвинутых системах, переменная типа Dimension ,скажем, не сможет иметь отрицательное значение

Опять же есть int, uint.

Может это где-то и оправдано, но в большинстве проектов нет. Мы же здесь про упрощение кода говорим?

Был бы благодарен за реальный пример, где использование подтипов оправдано.

1
23 ...

Information

Rating
Does not participate
Registered
Activity