суббота, 17 марта 2012 г.

[prog] Маленькое дополнение к недавней заметке о читабельности кода

В комментарии к недавней заметке о читабельности кода прозвучала мысль о том, что хорошо было бы сделать возвращаемое методом make_and_send_packages значение именованным. Безотносительно к моему собственному мнению на сей счет, это хороший повод вспомнить принцип Command/Query Separation, который лежит в основе идеологии языка Eiffel.

Если следовать этому принципу, то в моем прикладном агенте не должно было бы быть метода make_and_send_packages. Вместо него потребовался бы вспомогательный класс package_maker_and_sender_t с методом-командой make_and_send и методом-запросом number_of_packages_sent. Который бы использовался следующим образом:

if( !messages->empty() ) 

  package_maker_and_sender_t sender( *messages, /* плюс еще какие-то параметры */ );

  sender.make_and_send();

  m_load_batcher.increment_current_load( sender.number_of_packages_sent() ); 
}

В Eiffel-е принцип разделения методов на команды и запросы является одним из краеугольных. Мне же представляется, что такое жесткое разделение не всегда разумно. Может из-за того, что я учился программировать на процедурных языках, где функция могла производить побочный эффект (открывать файл, например) и возвращать значение. Поэтому я не вижу в таком подходе ничего плохого. Может из-за того, что command/query separation principle ведет к распуханию кода – туча мелких вспомогательных классов + выполнение самих действий удваивается в объеме: сначала вызов command-метода, затем query-метода. Upd. Забыл про еще один негативный момент: в таких вспомогательных методах появляется лишняя забота о том, чтобы методы вызывались в должном порядке. Так, объект класса package_maker_and_sender_t должен бить программиста по рукам, если тот вызывает number_of_packages_sent до вызова make_and_send. Что так же увеличивает объем работы программиста.

С другой стороны, принцип весьма простой, местами удобный. Особенно в ОО-языках, где нет понятия константности объектов и их методов (т.е. Java, C#, Eiffel, Ruby и пр.). Поэтому вполне может использоваться на практике. В частности, в упомянутой заметке на таком принципе работает класс load_batcher_t, который обладает методами-командами check_for_new_period и increment_current_load, а так же методом-запросом remaining_load.

PS. При следовании принципу Command/Query Separation методы-запросы начинают выступать в роли “чистых функций”, т.е. не меняющих состояние объекта и, по идее, всегда возвращающих одинаковый результат (если только они обращаются к каким-то изменяющимся из-вне объектам). Что может вносить в обычные ОО-языки некоторое подобие функциональщины, где функции не имеют побочных эффектов. Но только подобие, очень бледное ;)

3 комментария:

PSV100 комментирует...

У меня несколько офтопный вопросик. Евгений, а почему именно такой стиль оформления исходников ?
Я давно заметил, что Вы большой поклонник подчёркиваний, когда-то и style guide ваш читал. Я в С++ не большой спец, для меня он не основной язык, но under_score мне тоже симпатичен. Но когда длинные имена вида m_rescan_db_for_resending, или m_cfg.m_diagnostic_logging.m_rescan_db_for_resending - уже как-то не очень приятны. Конечно, хорошо, когда имена сразу говорят многое, а возможно в CamelCase это было бы ещё ужаснее, такие имена хорошо глотает лисп, в остальных случаях нужно искать компромисс. Всё-таки уже опыт, возраст, начинаешь на вещи смотреть все трезвее и трезвее, и мальчишеский пыл угасает, в том числе. Также вроде есть опыт работы в Java, вроде и Go щупался, где тоже навязывают CamelCase. Одним словом, не возникает ли желания что-то пересмотреть?

Я почему спрашиваю. Я сейчас вынужден немного "философствовать" по этому вопросу. Даже тему на РСДН-е завёл, она здесь: http://www.rsdn.ru/forum/flame.comp/4663504.1.aspx.
А здесь в блоге такая тема про читабельность кода опять заставила задуматься.

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

Спасибо.

eao197 комментирует...

@PSV100:

Я уже писал об этом некоторое время назад. Так что дам ссылку на себя самого: http://eao197.blogspot.com/2011/12/progmemories-camelcase-lowercase.html

PSV100 комментирует...

Блог читаю редко, всего не замечаю.
Спасибо.