Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
chpasha
Андрей Панфилов
а зачем удалять?

сеньор-то - пьяный. а в коде на Scala он и трезвый побоится удалять, разве что все скопом ;)


В ФП фишка в том что компилятор за тебя контролирует типы,и да, ты не сможешь удалить вызов транзактора и при этом не поломать сборку.
1 окт 19, 17:26    [21984159]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
mayton
Member

Откуда: loopback
Сообщений: 42385
andreykaT
mayton
Я-бы ограничился обычным каментом. Типа - "Перед тем как удалять - хорошо подумай. Если все таки решил удалять подойди
к Atum и спроси разрешения".

Все. Баста. Решение на 0.001 story point.

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

Плохая мода.

Но Роб Мартин прав в части того что каменды надо также суппортить как и код.
1 окт 19, 17:26    [21984160]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
andreykaT
поведение кода закрепляют тесты. ответ - надо покрыть код тестами.


Лучший тест - это компиляция, которую не забудешь проранать
1 окт 19, 17:28    [21984161]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3334
забыл ник
Никак, но в этом и весь цимус, что вам это и не надо.

Чет какая-то жесть...
- проблема: очень печально что мы не видим где транзакция начинается (в endpoint транзакции начинаются по канону)
- решение: берем скалу, теперь мы все равно не знаем где начинается транзакция, но проблемы уже нет - теперь у нас жопа в другом месте

забыл ник
А чтобы выполнить ConnectionIO - ты обязан предоставить Transactor, иначе не скомпилируется.
Как по мне так никакой практической пользы тут нет, транзакции же определяют как мы должны работать с данными, а тут нам язык какую-то конвенцию придумывает. А что делать если определенное метод мне нужно вне транзакции запустить, а если нужно параллельную транзакцию открыть?
1 окт 19, 17:39    [21984175]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

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


Да с чего вдруг? На самом деле идея простая, но не сразу дается, когда переходишь со спринга(сам так тупил)

UserService{
def insertUser = ... return Connection[User] 
def updateAudit = ... return Connection[Boolean]
}

MailService{
sendEmail = ... return IO
}

UserController(transactor:Transactor)

def insertUser = {
   val useCase:Connection[String] = for {
      user <- UserService.insert
      result <- UserService.audit
      _ <- if(result) MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}

def insertUserNoAudit = { 
   val useCase:Connection[String] = for {
      user <- UserService.insert
      _ <- MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}


В целом - sendEmail, insertUser - маленькие кусочки реюзаемой логики, никаких cross-cutting concerns.
В Контроллере ты компонуешь эти кусочки как вздумается, и когда тебе нужен результат(а не дескрипшен твоего действия) - передаешь туда транзактор, обычно это как раз в эндпоинтах контроллера.
1 окт 19, 17:56    [21984202]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
Андрей Панфилов
Как по мне так никакой практической пользы тут нет, транзакции же определяют как мы должны работать с данными, а тут нам язык какую-то конвенцию придумывает. А что делать если определенное метод мне нужно вне транзакции запустить, а если нужно параллельную транзакцию открыть?


Выполнить кусок кода вне транзакции не получится в любом случае. Если нужна параллельная - ну вызывай в другом потоке, транзактор тредсейф. А вообще звучит как "а ваша пила умеет сталь пилить?", хотелки какие-то непонятные, хотя прикол в том, что даже их без проблем можно реализовать
1 окт 19, 17:58    [21984208]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3334
забыл ник
Андрей Панфилов
Чет какая-то жесть...
- проблема: очень печально что мы не видим где транзакция начинается (в endpoint транзакции начинаются по канону)
- решение: берем скалу, теперь мы все равно не знаем где начинается транзакция, но проблемы уже нет - теперь у нас жопа в другом месте


Да с чего вдруг? На самом деле идея простая, но не сразу дается, когда переходишь со спринга(сам так тупил)

UserService{
def insertUser = ... return Connection[User] 
def updateAudit = ... return Connection[Boolean]
}

MailService{
sendEmail = ... return IO
}

UserController(transactor:Transactor)

def insertUser = {
   val useCase:Connection[String] = for {
      user <- UserService.insert
      result <- UserService.audit
      _ <- if(result) MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}

def insertUserNoAudit = { 
   val useCase:Connection[String] = for {
      user <- UserService.insert
      _ <- MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}


В целом - sendEmail, insertUser - маленькие кусочки реюзаемой логики, никаких cross-cutting concerns.
В Контроллере ты компонуешь эти кусочки как вздумается, и когда тебе нужен результат(а не дескрипшен твоего действия) - передаешь туда транзактор, обычно это как раз в эндпоинтах контроллера.

В данном случае (исходим из обсуждаемого примера) получается так:
чтобы дернуть MailService мне его нужно его заврапить в ConnectionIO (там в статье пишут IO.to[ConnectionIO]), поэтому везде по приведенному коду мне нужно расставить этот .to[ConnectionIO] "чтобы скомпилировалось", дальше проходит время, я выхожу из запоя и принимаю решение что почту мне нафиг посылать не нужно прямо вот сейчас, а можно и через некоторое время, поэтому я иду и меняю реализацию MailService чтобы оно писало в БД вместо отправки почты, а потом бегаю по всему коду и убираю .to[ConnectionIO] потому что теперь не компилируется - какое-то сомнительное удовольствие кмк.

забыл ник
Выполнить кусок кода вне транзакции не получится в любом случае. Если нужна параллельная - ну вызывай в другом потоке, транзактор тредсейф. А вообще звучит как "а ваша пила умеет сталь пилить?", хотелки какие-то непонятные, хотя прикол в том, что даже их без проблем можно реализовать
Здрасьте, требования как требования (ну вот спринг же умеет, а он ориентирован на JSR 907, который не последние люди в мире жавы разрабатывали), да и вызов в другом потоке и открытие новой транзакции из текущего - это два совершенно разных паттерна.
1 окт 19, 18:26    [21984233]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
andreykaT
Member

Откуда:
Сообщений: 2421
chpasha
andreykaT
не писать вообще принципиально никаких комментов по коду. потому что мартин так в своей книжке чистый код сказал

Мартин ничего не говорил про "не писать принципиально"
автор
Therefore, though comments are sometimes necessary, we will expend significant energy to minimize them.


Узбекская поговорка это только подтверждает ;)

конечно не говорил. вернее, он говорил типа не пишите избыточные комменты и не пишите бесплезные комменты. но норот читает как "не пишите комменты". ))) и начинаются в ревью тёрки типа у тебя код говно потому что ты вон там коммент оставил. а не только в шапке через жавадог
1 окт 19, 18:57    [21984282]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
andreykaT
Member

Откуда:
Сообщений: 2421
забыл ник
andreykaT
поведение кода закрепляют тесты. ответ - надо покрыть код тестами.


Лучший тест - это компиляция, которую не забудешь проранать

а причем в данном случае компиль? код то работает. просто он не так работает как ожидает тс. поведение кода контролируется тестами. имхо. про ваши фп как обходиться без тестов и вообще всё само я пока не вник. не у кого поучиться )
1 окт 19, 18:59    [21984288]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
andreykaT
Member

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


Да с чего вдруг? На самом деле идея простая, но не сразу дается, когда переходишь со спринга(сам так тупил)

UserService{
def insertUser = ... return Connection[User] 
def updateAudit = ... return Connection[Boolean]
}

MailService{
sendEmail = ... return IO
}

UserController(transactor:Transactor)

def insertUser = {
   val useCase:Connection[String] = for {
      user <- UserService.insert
      result <- UserService.audit
      _ <- if(result) MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}

def insertUserNoAudit = { 
   val useCase:Connection[String] = for {
      user <- UserService.insert
      _ <- MailService.sendEmail
   } yield "OK"
   useCase.run(transactor)
}


В целом - sendEmail, insertUser - маленькие кусочки реюзаемой логики, никаких cross-cutting concerns.
В Контроллере ты компонуешь эти кусочки как вздумается, и когда тебе нужен результат(а не дескрипшен твоего действия) - передаешь туда транзактор, обычно это как раз в эндпоинтах контроллера.


так вот он я красавец. у меня есть юзкейс.ран(транзактор), а есть скажем юзкейс.ватеварелз(неТранзактар)
и я такой модный программист - просто удаляю эту строку и подменяю другой. оно дальше допустим, работает но уже без транзакции.
1 окт 19, 19:02    [21984290]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
fixxer
Member

Откуда:
Сообщений: 720
забыл ник
Есть куда деваться. Как раз вот статья вышла хорошая, но это нужно иметь кое-какие знания о ФП чтобы понять.
Тыц


Спасибо, отличная статья. Идея о том, что из репозиториев можно возвращать DBIOAction[T] вмето Future[T] (у меня слик) и потом транзакционно интерпретировать в Application Service, лично для меня закрывает один из пробелов между классическим DDD и функциональным стилем.
1 окт 19, 23:07    [21984402]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2089
забыл ник
PetroNotC Sharp
пропущено...

Но жто декларативное управление транзакциями. Мейнстрим счас. Куда деваться.


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

Это конечно не совет автору все переписывать с нуля Картинка с другого сайта. - просто чтоб знал как бывает иначе
ох боюсь это никому не надо. Так как усложняет.
Надо 2 транзакции, пиши 2 потока или 2 раза beginTran.
Всё.
2 окт 19, 02:54    [21984462]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2089
fixxer
функциональным стилем.
а рвзве ФП стало распространено?
2 окт 19, 02:56    [21984463]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
fixxer
Member

Откуда:
Сообщений: 720
PetroNotC Sharp
fixxer
функциональным стилем.
а рвзве ФП стало распространено?


В скале так точно. Но даже в джаве последние три года встречаю, в основном, реактивные стримы и Completable Future.
2 окт 19, 10:13    [21984571]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
mayton
Member

Откуда: loopback
Сообщений: 42385
fixxer
PetroNotC Sharp
пропущено...
а рвзве ФП стало распространено?


В скале так точно. Но даже в джаве последние три года встречаю, в основном, реактивные стримы и Completable Future.

Если посмотреть более шИроко. То ФП давно уже вокруг вас. ФП - это не только программирование.
Это декларативное описание грамматик и смыслов. Формы Бекуса Науэра BNF/EBNF. Xml-schema/DTD.
Просто спеки для всяких DSL. И попытки втащить в языки программирования иммутабельность структур
данных - это всё части ФП.
2 окт 19, 10:30    [21984592]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
SpringMan
Member

Откуда:
Сообщений: 9
Atum1
Любые идеи, подойдут.

Как возможный вариант - на методы дао/репозитории вешать Transactional.MANDATORY
2 окт 19, 11:03    [21984630]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
SpringMan
Member

Откуда:
Сообщений: 9
SpringMan
Как возможный вариант - на методы дао/репозитории вешать Transactional.MANDATORY

С каким-нибудь тестом, разумеется.
2 окт 19, 11:05    [21984635]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
pavel_nv
Member

Откуда: NV -> SpB
Сообщений: 260
нужно понимать где у тебя в проекте вообще наставлены эти @Transactional
если это, как обычно - в контроллере для доступа к слою сервисов - то я бы сделал отдельный слой, который отвечает только транзакции совместно с мавен-модулями. напирмер

project
|
|- web (содержит контроллеры, имеет доступ только к интерфейсу core-api и DTOшки)
|
|- core api (содержит только интерфейс (какой нибудь BusinessService) и, вероятно, DTO)
|
|- core impl (содежит реализацию BusinessServiceImpl, весь класс помечен @Transactional, внутри редиректит логику уже в "настоящие" сервисы, вероятно конвертирует DTO в сущности JPA)

тут конечно "лишнего" кода будет много


Если конечно расстановка @Transactional имеет хаотичный характер - то, имхо, только интеграционные тесты) которые обращаются в систему через контроллеры
2 окт 19, 11:52    [21984691]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
mayton
Member

Откуда: loopback
Сообщений: 42385
Чувствую в этом топике рождается гоммункул.
2 окт 19, 12:26    [21984735]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
Андрей Панфилов
В данном случае (исходим из обсуждаемого примера) получается так:
чтобы дернуть MailService мне его нужно его заврапить в ConnectionIO (там в статье пишут IO.to[ConnectionIO]), поэтому везде по приведенному коду мне нужно расставить этот .to[ConnectionIO] "чтобы скомпилировалось", дальше проходит время, я выхожу из запоя и принимаю решение что почту мне нафиг посылать не нужно прямо вот сейчас, а можно и через некоторое время, поэтому я иду и меняю реализацию MailService чтобы оно писало в БД вместо отправки почты, а потом бегаю по всему коду и убираю .to[ConnectionIO] потому что теперь не компилируется - какое-то сомнительное удовольствие кмк.

Во-первых, тебе надо заворачивать MailService в ConnectionIO только в случае если ты хочешь вызвать его в рамках транзакции, в общем случае посылка email - это side-effect и должен быть обернут просто в IO. Верхний уровень программы выглядит примерно так:

def program = {
   IO db = DBLogic.run(transactor)
   IO log = saveLog
   IO mail = MailService.sendMail
   IO result = db *> log *> mail /// Тут код все еще не выполняется мы возвращаем всего лишь IO  - аля description of computation
}


Main {
   program.runUnsafe() // Реальный код выполняется здесь, все что находилось в IO тут разворачивается в значения Int, User т.д
}


Во-вторых, ты в чем-то прав, а именно в том что надо прикладывать усилия, чтобы код скопилировался. Но это происходит именно потому что мы прописываем в типе дополнительную информацию(а именно что коду нужно DB connection) - и если он не компилируется(ты поменял реализацию MailService) - то оно и не должно компилироваться, потому что коннекшен тебе не нужен.
И это не недостаток а достоинство. Тебя же не возмущает, если ты заменишь String date на LocalDate date - и тебе надо поменять все места, где используется это поле "чтобы скомпилировалось"?

С наскока это не понять, и даже за месяц.
Никого не уговариваю, хотите верьте, хотите нет - но composable type-safe transactions существуют
2 окт 19, 12:56    [21984770]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
andreykaT
забыл ник
пропущено...


Лучший тест - это компиляция, которую не забудешь проранать

а причем в данном случае компиль? код то работает. просто он не так работает как ожидает тс. поведение кода контролируется тестами. имхо. про ваши фп как обходиться без тестов и вообще всё само я пока не вник. не у кого поучиться )


А в том что ты в типах можешь прописать дополнительную логику. Некоторые умельцы чисто на типах пилят игры в пятнашки. И эти типы будут проверяться компилятором. И не по твоему хотению, а всегда. Их невозможно обойти и невозможно "забыть" запустить перед коммитом
2 окт 19, 12:58    [21984774]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
andreykaT
так вот он я красавец. у меня есть юзкейс.ран(транзактор), а есть скажем юзкейс.ватеварелз(неТранзактар)
и я такой модный программист - просто удаляю эту строку и подменяю другой. оно дальше допустим, работает но уже без транзакции.


Не поянл, какую строку удаляешь и почему оно перестанет работать? Любая операция с базой имеет тип ConnectionIO - единственный способ вытянуть оттуда реальное значение - это предоставить транзактор. Если ты не предоставишь - у тебя будет просто объект типа ConnectionIO и ты его не сможешь никак заюзать.
2 окт 19, 13:00    [21984781]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
fixxer
забыл ник
Есть куда деваться. Как раз вот статья вышла хорошая, но это нужно иметь кое-какие знания о ФП чтобы понять.
Тыц


Спасибо, отличная статья. Идея о том, что из репозиториев можно возвращать DBIOAction[T] вмето Future[T] (у меня слик) и потом транзакционно интерпретировать в Application Service, лично для меня закрывает один из пробелов между классическим DDD и функциональным стилем.


А DDD никак не противоречит ФП, а очень даже хорошо вписывается, я уже приводил линку - вот неплохая книга.

Functional-Reactive-Domain-Modeling
2 окт 19, 13:02    [21984783]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
PetroNotC Sharp
забыл ник
пропущено...


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

Это конечно не совет автору все переписывать с нуля Картинка с другого сайта. - просто чтоб знал как бывает иначе
ох боюсь это никому не надо. Так как усложняет.
Надо 2 транзакции, пиши 2 потока или 2 раза beginTran.
Всё.


Что усложняет? В хорошо написанной программе - Что в ООП, что в ФП по факту будет один и тот же результат(прочитать что-то, записать, залогировать, изменить стейт системы, обработать ошибки). И тебе и там и там надо обработать ошибки, обернуть все в транзакцию, обработать отсутсвие данных и т.д. В случае ООП обычно начинается с красивого кода по happy-path, а проверки на нулл, обработка эксепшенов, всякие корнер - кейсы - это уже по мере тестирования. В случае ФП - у тебя код просто не скопилируется пока ты все это не пропишешь.
Простота ООП иллюзорна и только расслабляет программиста, провоцируя его вовремя дэдлайнов на куяк куяк и в продакшен.
2 окт 19, 13:09    [21984800]     Ответить | Цитировать Сообщить модератору
 Re: Как защитить код  [new]
забыл ник
Member

Откуда:
Сообщений: 3024
PetroNotC Sharp
fixxer
функциональным стилем.
а рвзве ФП стало распространено?

Да, идеи ФП проникают в Java, C# и т.д, а не наоборот, как минимум. Тебе 10 лет назад показать код на стримах - ты бы ворочал носом и говорил какое говно, у меня есть циклы
2 окт 19, 13:11    [21984806]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
Все форумы / Java Ответить