Telegram Group & Telegram Channel
Принцип на все времена: Command-Query Separation

CQS очень простой принцип программирования, применение которого встречается на каждом шагу. Обычно его формулируют так: “задавая вопрос, не изменяй ответ”. Представьте что у вас есть функция, которая проверяет валидность объекта user.isValid(). По смыслу эта функция проверяет данные по каким-то правилам и возвращает true/false.

Может ли она что-то менять? Большинство скажет что это не логично и будет право. Она не должна ничего менять. На практике же, это происходит тут и там. В тех же Rails, вы легко встретите внутри модели колбек before_validation, в котором можно сделать любое изменение, которое сработает на вызов valid?. И этим часто пользуются, я был свидетелем, как в коде удалялись связи у пользователя. Но тоже самое встречается налево и направо у программистов во всех языках.

Однажды, когда я собесил человека на наставника в Хекслет, мы как-то по пути выяснили, что у них там в коде во время запроса каких-то опций, они удалялись из списка опций, мы обсудили этот момент, я чуть-чуть рассказал про CQS и разработчик мне ответил, что после разговора пойдет переписывать код :)

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

Кстати да, это правило распространяется на все вокруг. Именно поэтому в HTTP существует GET, который можно кешировать так как он сам не меняет данные (но данные могут поменяться по другим причинам), а POST всегда меняет, поэтому кеширование к нему не применяется.

Буквально недавно мы разговаривали с Тагиром и он поделился тем как в Java работает форматирование дат. Оказалось, что в Java есть объект SimpleDateFormat, и он непотокобезопасен. Почему? Потому что метод, который вроде бы просто форматирует дату в строку, на самом деле меняет внутреннее состояние объекта. И если два потока одновременно вызовут .format(…), то они могут получить некорректный результат. Это классический пример нарушения CQS: метод, выглядящий как query (просто возвращает значение), внезапно ведёт себя как command — вносит изменения.

В результате приходится либо каждый раз создавать новый SimpleDateFormat, либо оборачивать его в ThreadLocal, либо использовать DateTimeFormatter из более нового API, который как раз спроектирован с учётом CQS — он ничего не мутирует.

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

Но это что касается вопросов. А что насчет команд? Тут уже не так очевидно, почему если мы выполняем действие (`setSomething()`, doSomething(), то данные лучше не возвращать?

Во-первых, это снова вопрос читаемости и предсказуемости. Метод с названием deleteUser(id) должен просто удалить пользователя, а не возвращать его профиль. Когда действие возвращает что-то, разработчики начинают полагаться на это значение: передавать его дальше, использовать как флаг, делать выводы.

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

Это не значит, что действия никогда ничего не возвращают. Иногда они могут вернуть, например, true или false, чтобы явно показать успех или неудачу. Более того, в некоторых ситуациях невозможно соблюдать CQS, например, при открытии файла на запись (создается файловый дескриптор).

Ссылки: Телеграм | Youtube | VK


p.s. Признавайтесь, писали такой код?



group-telegram.com/orgprog/309
Create:
Last Update:

Принцип на все времена: Command-Query Separation

CQS очень простой принцип программирования, применение которого встречается на каждом шагу. Обычно его формулируют так: “задавая вопрос, не изменяй ответ”. Представьте что у вас есть функция, которая проверяет валидность объекта user.isValid(). По смыслу эта функция проверяет данные по каким-то правилам и возвращает true/false.

Может ли она что-то менять? Большинство скажет что это не логично и будет право. Она не должна ничего менять. На практике же, это происходит тут и там. В тех же Rails, вы легко встретите внутри модели колбек before_validation, в котором можно сделать любое изменение, которое сработает на вызов valid?. И этим часто пользуются, я был свидетелем, как в коде удалялись связи у пользователя. Но тоже самое встречается налево и направо у программистов во всех языках.

Однажды, когда я собесил человека на наставника в Хекслет, мы как-то по пути выяснили, что у них там в коде во время запроса каких-то опций, они удалялись из списка опций, мы обсудили этот момент, я чуть-чуть рассказал про CQS и разработчик мне ответил, что после разговора пойдет переписывать код :)

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

Кстати да, это правило распространяется на все вокруг. Именно поэтому в HTTP существует GET, который можно кешировать так как он сам не меняет данные (но данные могут поменяться по другим причинам), а POST всегда меняет, поэтому кеширование к нему не применяется.

Буквально недавно мы разговаривали с Тагиром и он поделился тем как в Java работает форматирование дат. Оказалось, что в Java есть объект SimpleDateFormat, и он непотокобезопасен. Почему? Потому что метод, который вроде бы просто форматирует дату в строку, на самом деле меняет внутреннее состояние объекта. И если два потока одновременно вызовут .format(…), то они могут получить некорректный результат. Это классический пример нарушения CQS: метод, выглядящий как query (просто возвращает значение), внезапно ведёт себя как command — вносит изменения.

В результате приходится либо каждый раз создавать новый SimpleDateFormat, либо оборачивать его в ThreadLocal, либо использовать DateTimeFormatter из более нового API, который как раз спроектирован с учётом CQS — он ничего не мутирует.

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

Но это что касается вопросов. А что насчет команд? Тут уже не так очевидно, почему если мы выполняем действие (`setSomething()`, doSomething(), то данные лучше не возвращать?

Во-первых, это снова вопрос читаемости и предсказуемости. Метод с названием deleteUser(id) должен просто удалить пользователя, а не возвращать его профиль. Когда действие возвращает что-то, разработчики начинают полагаться на это значение: передавать его дальше, использовать как флаг, делать выводы.

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

Это не значит, что действия никогда ничего не возвращают. Иногда они могут вернуть, например, true или false, чтобы явно показать успех или неудачу. Более того, в некоторых ситуациях невозможно соблюдать CQS, например, при открытии файла на запись (создается файловый дескриптор).

Ссылки: Телеграм | Youtube | VK


p.s. Признавайтесь, писали такой код?

BY Организованное программирование | Кирилл Мокевнин




Share with your friend now:
group-telegram.com/orgprog/309

View MORE
Open in Telegram


Telegram | DID YOU KNOW?

Date: |

Telegram users are able to send files of any type up to 2GB each and access them from any device, with no limit on cloud storage, which has made downloading files more popular on the platform. Since its launch in 2013, Telegram has grown from a simple messaging app to a broadcast network. Its user base isn’t as vast as WhatsApp’s, and its broadcast platform is a fraction the size of Twitter, but it’s nonetheless showing its use. While Telegram has been embroiled in controversy for much of its life, it has become a vital source of communication during the invasion of Ukraine. But, if all of this is new to you, let us explain, dear friends, what on Earth a Telegram is meant to be, and why you should, or should not, need to care. However, the perpetrators of such frauds are now adopting new methods and technologies to defraud the investors. The Securities and Exchange Board of India (Sebi) had carried out a similar exercise in 2017 in a matter related to circulation of messages through WhatsApp. Telegram was founded in 2013 by two Russian brothers, Nikolai and Pavel Durov.
from us


Telegram Организованное программирование | Кирилл Мокевнин
FROM American