C++ IDE, которая поддерживает совет Скотта Мейера: предпочитать функции, не являющиеся членами, не являющиеся друзьями, а не члены

Аргумент Скотта Мейера о том, что функции, не являющиеся членами, увеличивают инкапсуляцию и обеспечивают более элегантный дизайн (с точки зрения дизайна), кажется мне очень верным. См. здесь: Статья

А вот с этим у меня проблемы. (И, похоже, другие тоже, особенно разработчики библиотек, которые обычно полностью игнорируют это)

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

Так что, возможно, у меня есть только одна проблема:

С функциями-членами я И моя IDE знают, что может делать класс.

Для меня это огромно! Я не использую для программирования ничего, что не поддерживает завершение кода функции-члена. В хорошо спроектированных библиотеках он полностью заменяет мне документацию. И даже если бы я посмотрел документацию API, просмотр списка участников кажется абсолютно естественным, логичным, и я могу быть уверен, что это конец. Если метода там нет, я могу с уверенностью предположить, что его не существует, и я могу написать свой не-член, не являющийся другом.

Я смирился с этим в STL, потому что имеет смысл рассматривать алгоритмы отдельно от основных компонентов и из-за фактора к этому привыкаешь.

Я не видел IDE, которая могла бы сказать мне, какие функции, не являющиеся членами, работают с конкретным классом.

И это на самом деле мой вопрос: существует ли IDE (или функция IDE), которая помогает с этим соглашением о коде?


person AndreasT    schedule 11.11.2009    source источник
comment
Я думаю, что на самом деле Мейерс намеревается написать все функции как можно более универсальными. Вы также можете сказать: предпочтите статические функции-члены нестатическим функциям-членам и избегайте дружбы, чтобы свести к минимуму зависимости. Таким образом, вы получите хорошую (многоразовую) абстракцию вашего алгоритма.   -  person fmuecke    schedule 11.11.2009
comment
Вы только что узнали на собственном горьком опыте, что аргумент для функций, не являющихся членами, переоценен.   -  person rpg    schedule 11.11.2009
comment
@rpg - вы действительно думаете, что принципы проектирования программного обеспечения должны диктоваться тем, что проще всего для вашей IDE?   -  person jon-hanson    schedule 11.11.2009
comment
@Джон. Я думаю, что на принципы проектирования программного обеспечения должно влиять все, что возможно для IDE. В этом случае, тем не менее, IDE должна иметь возможность очень легко находить не являющиеся членами не дружественные функции, относящиеся к MyClass, просто просматривая пространство имен, содержащее MyClass. При хорошем дизайне автора MyClass набор функций, доступных ADL с аргументом MyClass, следует рассматривать как часть общедоступного интерфейса набора. Моя IDE не поддерживает этот в остальном превосходный принцип проектирования, что не является основанием для того, чтобы считать виноватым принцип проектирования, а не IDE.   -  person Steve Jessop    schedule 11.11.2009
comment
@steve, я думаю, мы согласны.   -  person jon-hanson    schedule 12.11.2009


Ответы (4)


Я сталкивался с этим в прошлом.

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

То, что я сделал, было

namespace myclass
{
    class MyClass
    {
        ...
    };

    MyClass operator+(const MyClass& lhs, const MyClass& rhs){...}
}
person S.C. Madsen    schedule 11.11.2009
comment
+1, я не думаю, что это особенно неуклюже, хотя вам не обязательно нужно пространство имен для каждого класса. Преимущество заключается в том, что вы точно знаете, где получить список всех предоставляемых библиотекой вещей, которые можно сделать с MyClass. В частности, это задокументированный список функций в пространстве имен, содержащем MyClass. - person Steve Jessop; 11.11.2009

Мейерс, безусловно, прав в том, что использование не-членов увеличивает инкапсуляцию, сводя к минимуму количество функций, которые потенциально могут получить доступ к частному состоянию. Однако инкапсуляция — это лишь один из многих (часто противоречащих друг другу) аспектов качества кода.

Он делает обоснованное замечание, что автор библиотеки не обязательно будет писать функции для каждого возможного использования класса (поскольку могут быть случаи использования, о которых они не думают). Это означает, что вам, возможно, придется самостоятельно добавлять «вспомогательные» функции, не являющиеся членами, точно так же, как это сделали бы они, если бы последовали совету Мейерса. Таким образом, нет никакого способа узнать, что набор функций-членов и дружественных функций действительно является единственным набором функций, которые воздействуют на класс.

Как технолуддит, «IDE», которую я предпочитаю (текстовый редактор и оболочка), имеет следующую «особенность», которая очень удобна для поиска функций, действующих в классе:

find . -name '*.h' -o -name '*.cpp' | xargs grep MyClass

Я не могу комментировать «настоящие» IDE.

person Mike Seymour    schedule 11.11.2009
comment
Ну, я мог бы отобразить это в vim. Работает... ок. Знаете ли вы, есть ли способ ctags выполнить этот запрос? Я использую определенные файлы тегов для omnicomplete и т. д. Это должно быть выполнимо с ними, не так ли? - person AndreasT; 20.11.2009
comment
Я не знаю о vim или ctags — для меня это слишком высокотехнологично. Я бы посоветовал вам подумать о том, почему, по вашему мнению, вам нужна эта функциональность. Имейте в виду, что мы говорим о поиске всех функций, которые используют public интерфейс вашего класса — это может быть любая функция в любой точке мира (при условии, что она может получить доступ к определению класса). - person Mike Seymour; 20.11.2009
comment
Если вы последуете совету Мейерса (и других) и спроектируете свой класс так, чтобы он имел одну четко определенную цель и полный и минимальный интерфейс, который реализует эту цель и ничего больше, тогда вам не нужно менять интерфейс, как только он используется, поэтому не должно быть никаких причин отслеживать всех его пользователей. - person Mike Seymour; 20.11.2009

Я не верю, что IDE может рассказать вам обо всех функциях, не являющихся членами, которые вы можете использовать с вашим классом. Используя шаблоны, просто слишком сложно составить список всех таких функций. IMO, лучшее, на что вы можете надеяться, - это то, что IDE сможет сообщить вам перед компиляцией, является ли вызов, который вы пытаетесь сделать, действительным. И даже это требует серьезного процесса компиляции внутри IDE.

Я понимаю, как вы используете функции-члены в качестве замены документации в классических классах. Но дизайн, предложенный Скоттом Мейером, касается не классов, предоставляющих сложные функции, а только базовых. Сложные функциональные возможности приходят откуда-то еще, исходный класс может знать или не знать об этом, это не имеет большого значения. Это все часть идеи. Но вы правы. В этом случае возникает необходимость в хорошо продуманной документации.

person Benoît    schedule 11.11.2009
comment
Я не верю, что это возможно для IDE. Например, должна ли среда IDE перечислять std::swap как функцию, которую можно использовать для любого назначаемого класса, std::max для сопоставимых классов и т. д.? Список всех участников опроса также не обнаруживает эти алгоритмы. Так что я думаю, вы правы, говоря, что это в основном проблема без решения. - person Steve Jessop; 11.11.2009

Попробуйте использовать Visual AssistX, у него есть замечательная функция: Щелкните правой кнопкой мыши на своем классе, Refactor (VA X) -> Найти ссылки. Это действительно работает.

person Ferenc Deak    schedule 11.11.2009
comment
Отличается ли это от ссылки на поиск в Visual Studio? (2010 намного лучше с C++) - person Simon Buchan; 16.04.2010