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. Признавайтесь, писали такой код?



tg-me.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:
tg-me.com/orgprog/309

View MORE
Open in Telegram


telegram Telegram | DID YOU KNOW?

Date: |

How to Buy Bitcoin?

Most people buy Bitcoin via exchanges, such as Coinbase. Exchanges allow you to buy, sell and hold cryptocurrency, and setting up an account is similar to opening a brokerage account—you’ll need to verify your identity and provide some kind of funding source, such as a bank account or debit card. Major exchanges include Coinbase, Kraken, and Gemini. You can also buy Bitcoin at a broker like Robinhood. Regardless of where you buy your Bitcoin, you’ll need a digital wallet in which to store it. This might be what’s called a hot wallet or a cold wallet. A hot wallet (also called an online wallet) is stored by an exchange or a provider in the cloud. Providers of online wallets include Exodus, Electrum and Mycelium. A cold wallet (or mobile wallet) is an offline device used to store Bitcoin and is not connected to the Internet. Some mobile wallet options include Trezor and Ledger.

The STAR Market, as is implied by the name, is heavily geared toward smaller innovative tech companies, in particular those engaged in strategically important fields, such as biopharmaceuticals, 5G technology, semiconductors, and new energy. The STAR Market currently has 340 listed securities. The STAR Market is seen as important for China’s high-tech and emerging industries, providing a space for smaller companies to raise capital in China. This is especially significant for technology companies that may be viewed with suspicion on overseas stock exchanges.

telegram from sg


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