У меня есть коллега в моей компании, к мнению которого я очень уважаю, но я просто не могу понять один из его предпочтительных стилей написания кода на C ++.
Например, если есть класс A, он напишет глобальные функции типа:
void foo( A *ptrToA ){}
или
void bar( const A &refToA ){}
Мой первый инстинкт при взгляде на глобальные функции, подобные этому: «Почему это не члены A?» Он будет настаивать на том, что это согласуется с рекомендациями для хорошей практики в C ++, потому что foo и bar могут выполнять все, что им нужно, используя открытый интерфейс A. Например, он будет утверждать, что это полностью соответствует с Скоттом Мейерсом Эффективные рекомендации C ++. Мне трудно согласовать это с пунктом 19 в этой книге, в котором в основном говорится, что все должно быть функцией-членом с несколькими исключениями (operator << и operator >> и функции, которые требуют динамического преобразования типов). Кроме того, хотя я согласен с тем, что функции могут делать то, что им нужно, с общедоступным интерфейсом A, по моему мнению, это во многом является результатом того, что люди пишут классы, которые имеют методы получения и установки для каждого члена данных класса А. открытый интерфейс, A - это чрезмерно прославленная структура, и вы, безусловно, можете делать с открытым интерфейсом все, что угодно. Лично я не думаю, что это следует использовать, я думаю, что это не должно поощряться.
Очевидно, что это возможно только в языке, подобном C ++, который не является чисто объектно-ориентированным, поэтому я предполагаю, что один из способов взглянуть на это состоит в том, что мой коллега не одобряет чисто объектно-ориентированный подход к разработке программного обеспечения. Кто-нибудь знает какую-либо литературу, которая поддерживает эту позицию как лучшую практику? Или кто-то согласен с этим и может объяснить это мне иначе, чем мой коллега, чтобы я мог увидеть свет? Или все согласны с моим нынешним ощущением, что это не имеет особого смысла?
Изменить:
Позвольте мне привести лучший пример кода.
class Car
{
Wheel frontLeft;
Wheel frontRight;
Wheel rearLeft;
Wheel rearRight;
Wheel spareInTrunk;
public:
void wheelsOnCar( list< Wheel > &wheels )
{
wheels.push_back( frontLeft );
wheels.push_back( frontRight);
wheels.push_back( rearLeft);
wheels.push_back( rearRight);
}
const Wheel & getSpare(){ return spareInTrunk; }
void setSpare( const Wheel &newSpare ){ spareInTrunk = newSpare; }
// There are getters and setters for the other wheels too,
//but they aren't important for this example
};
Тогда я увижу функцию, подобную этой:
void wheelsRelatedToCar( Car *aCar, list< Wheel > &wheels )
{
aCar->wheelsOnCar( wheels );
wheels.push_back( aCar->getSpare() );
}
Это реальный пример с именами классов и функций, которые, конечно, были изменены. Почему кто-то хочет, чтобы wheelsRelatedToCar
не был членом функции Car? В этом реальном примере Car и Wheel были в одной библиотеке. Глобальная функция была определена в исходном файле в конкретном приложении, использующем эту библиотеку, поэтому был выдвинут аргумент, что функция специфична для приложения. Мой ответ состоял в том, что это была совершенно законная операция на автомобиле и принадлежала к классу автомобилей. Есть ли другая точка зрения на это (кроме тех, кто не предпочитает использовать объектно-ориентированный дизайн)?