Сложность все равно будет торчать - вот вы с ней и столкнулись. Либо вы уходите в шаманство с ORM, либо берете все в свои руки и изолируете уже в своем подконтрольном слое данных.
У нас везде используются простые анемичные модели (почти структуры в терминологии языка си) на слое данных. В качестве запросов либо сырые запросы, либо простые генераторы запросов. Выглядит дорого по количеству кода, но в поддержке код несложный, и максимально оптимально в рантайме относительно взаимодействия с базой. В хорошем языке это все присыпается сахаром и выглядит не сильно хуже.
В правильной архитектуре проекта все равно вы увидите насколько небольшое число вариантов изменения и выборки сущностей реально необходимо. Плюсом не теряется синтаксис массовых обновлений (опасненько конечно, но иногда важно), которые раньше возможно было делать только поштучным апдейтом после массовой материализации (понятно что можно в сырой sql всегда уйти, но это не по феншую при ActiveRecord).
В современном сообществе принято считать что монетизация косметики в мультиплеерной бесплатной игре это не проблема. Лутбоксы (в любом их проявлении) обычно осуждаются ибо паразитируют на азарте. Детям монетизацию надо запретить прямо жесточайше, просто рейтинг 18+ на все условно-бесплатные игры с монетизацией. Но с другой стороны дети в большинстве своем карт не имеют для оплаты - значит дают родители, это их выбор. А государство лезущее в воспитание детей - худшее из возможных зол
Active Record везде где работал в энтерпрайзе запрещен или является антипатерном по умолчанию. Именно из-за подобного класса проблем и неадекватного потребления ресурсов. Но у меня стек другой )
Это все весело, но работает только если ключи никогда не покидают пользовательского устройства, и условный гос орган от твоего имени что-то подписать физически не может. В данной схеме ключи выдаются в гос органе (ЦОНе) и генерятся там же. Для подписи нужно ставить гос приложение а не примитивный скрипт или свободное ПО. Так что система защищена очень слабо именно из-за способа выдачи ключей - глобально. + Гос орган сам имеет доступ к ключам, есть место для подлога. + Гос приложение на устройстве пользователя
Может эти репрессивные меры приведут таки к чему-то хорошему? Не подумали? Может наконец жадные до личных данных товарищи тупо *много мата - вырезано* перестанут накапливать персоналку? И вообще ее хранить?
Такое ощущение что у вас в проектах в стеке вызовов глубины больше 3х не бывает. Вот как мне кинуть 400 (или вообще что-то осмысленное) - нет строки в резалтсете когда 10 сервис по глубине обработки запроса не нашел нужную запись? Ну нет ее, a) все 10 сервисов должны в вызове try-pattern иметь? - очевидно нет, б) мне null вернуть чтобы оно упало непонятно где? - очевидно нет, в) мне подогнать запрос так чтобы упало с sqlexception без записей? - очевидно нет, г) throw вы мне делать запретили. Для меня это и есть 99% ситуаций когда я без зазрения совести кину throw, хоть он и бизнесовый наверно по сути. Более того я кину особое исключение которое мидлварь перепакует в правильный http ответ, с адекватным текстом д) В теории есть вариант прокинуть именно это странное состояние в моделях всех вызовов сервисов выше, по всем правилам перепаковывая перехватывая по пути. Вы так сделаете ради реально редкого кейса? е) затеять лютый рефакторинг и редизайн и избавится от самой возможности подобной ситуации не важно какой ценой?
Это достаточно близко к описанию причин такого подхода от авторов языка. Этот подход рожден на основе богатого опыта крупной компании, да он серьезно ломает устои - принять его тяжело, но я с ним работал в крупном проекте и прочувствовал последствия, удобства и недостатки. Проблемы он реально решает причем не по месту, а глобально и привентивно. Подход майкрософта однобокий - пользуйтесь тем и тем, но вот Exception это очень дорого и лучше ненадо, для бизнес исключений по сути нельзя. Удобная позиция не дать инструмента для полноценной замены но при этом сказать что этим вот не пользуйтесь - оно медленное. Т.е. я должен под неоптимальность в рантайме подстраивать обработку бизнес процесса в коде на языке высокого уровня. При этом не мелочь какая-то по месту оптимизация, а прямо глобально архитектурно подстроиться.
Есть проблемы 1) разрабы игнорят ошибки - go явно требует результат присвоить, линтер даст по рукам 2) разрабы не перепаковывают ошибки по слоям - go дает простой способ 3) try-catch дорогой по ресурсам - go подход дешевый 4) try-catch передает управление вверх по стеку фиг знает куда - go требует всегда обрабатывать по месту 5) try-pattern ломает сигнатуру метода - в go это стандарт работы и выглядит аккуратно 6) try-pattern теряет причину ошибки - в go все на месте x) проблемы из errorcode не вписываю Новые проблемы 1) гребаные if err=!nil return повсеместно - решаются ide (сворачивают автоматом в конец выражения), может добавят какой сахарок в будущем 2) принято приводить возврат к базовому типу error и приходится на уровень выше иногда кастить типы - терпим, большинство библиотек в виде исходников, виды исключений доступны
check городить не нужно, нужно прям на месте что-то сделать или упаковать и кинуть выше. Сложный check нужен раз в тысячу лет. Так что проблем что все методы стали "try-pattern" нет - неявно многие методы в шарпе могут ошибку кинуть, а тут все явно и понятно
Мы вернулись к тому с чего начали - этот микропример не решает вопроса заразности. //do something without x 99.9% случаев вы ничего не можете сделать кроме как прервать работу функции вернув ошибку выше и там также получив из этого метода ошибку вы тоже ничего сделать не сможете кроме как подняться выше... Вот у меня вопрос про заразность - и возникает
я обсуждаю не exception как примитив конкретного языка, а то что при обработке исключительных ситуаций лучше иметь нормальную информацию о них соответствующую слою приложения. То что try catch дорогой не значит что нужно сразу уходить от него в примитивизм bool в качестве признака ошибки. try-pattern будет часто заражать весь стек вверх тем что если одна функция "не смогла", то и все вышестоящие тоже не смогут. Отсюда у вас все интерфейсы методов в приложении станут bool TrySomething(params, out returnType), это логично проистечет из повсеместного try-pattern. Go пришел именно к тому что вы предлагаете, и в теории в C# нет проблемы повторить этот подход. Ваши примеры очень простые, и вы не видите как этот подход будет выглядеть если на десятом уровне вызовов произойдет ошибка записи в БД или какая-нибудь исключительная ситуация в данных? Это значит 10 методов будут иметь try-pattern сигнатуру, в этом случае. А так как большинство приложений построены вокруг обращений к бд или внешним ресурсам (чистая математика редкая) - то у вас вообще других сигнатур не останется в приложении.
это неудобный способ записи того же самого, но ошибку вы даже не текстом вернули а boolean. Теперь примерьте ваш подход с отказом от out с заменой на несколько значений возвращаемых из функции + стандарт на тип ошибки (не bool) и получите подход из go
именно. Ошибки нижнего слоя логически не должны просачиваться наверх - это нарушение инкапсуляции и создает необоснованную привязку к реализации нижестоящих слоев. В go эта семантика дешевле в обработке и органичнее
Сложность все равно будет торчать - вот вы с ней и столкнулись. Либо вы уходите в шаманство с ORM, либо берете все в свои руки и изолируете уже в своем подконтрольном слое данных.
У нас везде используются простые анемичные модели (почти структуры в терминологии языка си) на слое данных. В качестве запросов либо сырые запросы, либо простые генераторы запросов. Выглядит дорого по количеству кода, но в поддержке код несложный, и максимально оптимально в рантайме относительно взаимодействия с базой. В хорошем языке это все присыпается сахаром и выглядит не сильно хуже.
В правильной архитектуре проекта все равно вы увидите насколько небольшое число вариантов изменения и выборки сущностей реально необходимо. Плюсом не теряется синтаксис массовых обновлений (опасненько конечно, но иногда важно), которые раньше возможно было делать только поштучным апдейтом после массовой материализации (понятно что можно в сырой sql всегда уйти, но это не по феншую при ActiveRecord).
В современном сообществе принято считать что монетизация косметики в мультиплеерной бесплатной игре это не проблема. Лутбоксы (в любом их проявлении) обычно осуждаются ибо паразитируют на азарте. Детям монетизацию надо запретить прямо жесточайше, просто рейтинг 18+ на все условно-бесплатные игры с монетизацией. Но с другой стороны дети в большинстве своем карт не имеют для оплаты - значит дают родители, это их выбор. А государство лезущее в воспитание детей - худшее из возможных зол
Active Record везде где работал в энтерпрайзе запрещен или является антипатерном по умолчанию. Именно из-за подобного класса проблем и неадекватного потребления ресурсов. Но у меня стек другой )
Погодите - я сначала прихожу в Цон и потом иду в софт - не наоборот. Можете подробно описать как работает?
Это все весело, но работает только если ключи никогда не покидают пользовательского устройства, и условный гос орган от твоего имени что-то подписать физически не может.
В данной схеме ключи выдаются в гос органе (ЦОНе) и генерятся там же. Для подписи нужно ставить гос приложение а не примитивный скрипт или свободное ПО.
Так что система защищена очень слабо именно из-за способа выдачи ключей - глобально. + Гос орган сам имеет доступ к ключам, есть место для подлога. + Гос приложение на устройстве пользователя
Да, если данные о сбое не теряет и перепаковывает по пути. В go так и сделано) В шарпе нам запрещают (г) в замен предлагают ничего - делайте (д) и (е)
Ну вот мне и интересно что по мнению автора нужно делать? )
Может эти репрессивные меры приведут таки к чему-то хорошему? Не подумали? Может наконец жадные до личных данных товарищи тупо *много мата - вырезано* перестанут накапливать персоналку? И вообще ее хранить?
Такое ощущение что у вас в проектах в стеке вызовов глубины больше 3х не бывает. Вот как мне кинуть 400 (или вообще что-то осмысленное) - нет строки в резалтсете когда 10 сервис по глубине обработки запроса не нашел нужную запись? Ну нет ее,
a) все 10 сервисов должны в вызове try-pattern иметь? - очевидно нет,
б) мне null вернуть чтобы оно упало непонятно где? - очевидно нет,
в) мне подогнать запрос так чтобы упало с sqlexception без записей? - очевидно нет,
г) throw вы мне делать запретили. Для меня это и есть 99% ситуаций когда я без зазрения совести кину throw, хоть он и бизнесовый наверно по сути. Более того я кину особое исключение которое мидлварь перепакует в правильный http ответ, с адекватным текстом
д) В теории есть вариант прокинуть именно это странное состояние в моделях всех вызовов сервисов выше, по всем правилам перепаковывая перехватывая по пути. Вы так сделаете ради реально редкого кейса?
е) затеять лютый рефакторинг и редизайн и избавится от самой возможности подобной ситуации не важно какой ценой?
Вы как поступаете в такой ситуации?
Это достаточно близко к описанию причин такого подхода от авторов языка. Этот подход рожден на основе богатого опыта крупной компании, да он серьезно ломает устои - принять его тяжело, но я с ним работал в крупном проекте и прочувствовал последствия, удобства и недостатки. Проблемы он реально решает причем не по месту, а глобально и привентивно.
Подход майкрософта однобокий - пользуйтесь тем и тем, но вот Exception это очень дорого и лучше ненадо, для бизнес исключений по сути нельзя. Удобная позиция не дать инструмента для полноценной замены но при этом сказать что этим вот не пользуйтесь - оно медленное.
Т.е. я должен под неоптимальность в рантайме подстраивать обработку бизнес процесса в коде на языке высокого уровня. При этом не мелочь какая-то по месту оптимизация, а прямо глобально архитектурно подстроиться.
Есть проблемы
1) разрабы игнорят ошибки - go явно требует результат присвоить, линтер даст по рукам
2) разрабы не перепаковывают ошибки по слоям - go дает простой способ
3) try-catch дорогой по ресурсам - go подход дешевый
4) try-catch передает управление вверх по стеку фиг знает куда - go требует всегда обрабатывать по месту
5) try-pattern ломает сигнатуру метода - в go это стандарт работы и выглядит аккуратно
6) try-pattern теряет причину ошибки - в go все на месте
x) проблемы из errorcode не вписываю
Новые проблемы
1) гребаные if err=!nil return повсеместно - решаются ide (сворачивают автоматом в конец выражения), может добавят какой сахарок в будущем
2) принято приводить возврат к базовому типу error и приходится на уровень выше иногда кастить типы - терпим, большинство библиотек в виде исходников, виды исключений доступны
check городить не нужно, нужно прям на месте что-то сделать или упаковать и кинуть выше. Сложный check нужен раз в тысячу лет. Так что проблем что все методы стали "try-pattern" нет - неявно многие методы в шарпе могут ошибку кинуть, а тут все явно и понятно
Но go мне все еще не нравится - выше просто факты
Мы вернулись к тому с чего начали - этот микропример не решает вопроса заразности.
//do something without x
99.9% случаев вы ничего не можете сделать кроме как прервать работу функции вернув ошибку выше и там также получив из этого метода ошибку вы тоже ничего сделать не сможете кроме как подняться выше...
Вот у меня вопрос про заразность - и возникает
У нас что сезонное обострение? Астрологи объявили неделю тролей - количество набросов на вентилятор увеличено вчетверо?
Как вы решали заразность try-pattern при замене исключений?
Я не сказал что гошный хорош) Но это еще хуже. Гошный хотябы целостный и решает проблемы, не привнося сильно много новых
Вот в этих условиях и приходим к стандартному по умолчанию try catch и редкому по месту try-pattern. Так к чему тогда обсуждение?
Описал выше - ваш вариант хуже гошного.
я обсуждаю не exception как примитив конкретного языка, а то что при обработке исключительных ситуаций лучше иметь нормальную информацию о них соответствующую слою приложения. То что try catch дорогой не значит что нужно сразу уходить от него в примитивизм bool в качестве признака ошибки. try-pattern будет часто заражать весь стек вверх тем что если одна функция "не смогла", то и все вышестоящие тоже не смогут. Отсюда у вас все интерфейсы методов в приложении станут bool TrySomething(params, out returnType), это логично проистечет из повсеместного try-pattern. Go пришел именно к тому что вы предлагаете, и в теории в C# нет проблемы повторить этот подход. Ваши примеры очень простые, и вы не видите как этот подход будет выглядеть если на десятом уровне вызовов произойдет ошибка записи в БД или какая-нибудь исключительная ситуация в данных? Это значит 10 методов будут иметь try-pattern сигнатуру, в этом случае. А так как большинство приложений построены вокруг обращений к бд или внешним ресурсам (чистая математика редкая) - то у вас вообще других сигнатур не останется в приложении.
это неудобный способ записи того же самого, но ошибку вы даже не текстом вернули а boolean. Теперь примерьте ваш подход с отказом от out с заменой на несколько значений возвращаемых из функции + стандарт на тип ошибки (не bool)
и получите подход из go
именно. Ошибки нижнего слоя логически не должны просачиваться наверх - это нарушение инкапсуляции и создает необоснованную привязку к реализации нижестоящих слоев. В go эта семантика дешевле в обработке и органичнее