DoSomethingToThing (Thing n) против Thing.DoSomething () - PullRequest
12 голосов
/ 17 сентября 2008

Какие факторы определяют, какой подход является более подходящим?

Ответы [ 16 ]

14 голосов
/ 17 сентября 2008

Я думаю, что у обоих есть свои места.

Вы не должны просто использовать DoSomethingToThing(Thing n) только потому, что считаете «функциональное программирование - это хорошо». Точно так же вы не должны просто использовать Thing.DoSomething(), потому что «Объектно-ориентированное программирование - это хорошо».

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

Например, если часть «предложения», которую вы хотели бы подчеркнуть, является объектом, вы должны использовать стиль OO.

Пример:

fileHandle.close();

В большинстве случаев, когда вы передаете дескрипторы файлов, главное, о чем вы думаете, это отслеживать файл, который он представляет.

контрпример:

string x = "Hello World";
submitHttpRequest( x );

В этом случае отправка HTTP-запроса гораздо важнее, чем строка, являющаяся телом, поэтому submitHttpRequst(x) предпочтительнее x.submitViaHttp()

Излишне говорить, что они не являются взаимоисключающими. Вы, вероятно, на самом деле будете иметь

networkConnection.submitHttpRequest(x)

, в котором вы смешиваете их обоих. Важно то, что вы думаете о том, какие части выделены, и что вы будете передавать будущему читателю кода.

8 голосов
/ 17 сентября 2008

Чтобы быть объектно-ориентированным, скажите, не спрашивайте: http://www.pragmaticprogrammer.com/articles/tell-dont-ask.

Итак, Thing.DoSomething (), а не DoSomethingToThing (Thing n).

3 голосов
/ 17 сентября 2008
  1. Thing.DoSomething подходит, если Thing является предметом вашего предложения.
    • DoSomethingToThing (Thing n) подходит, если Thing является объектом вашего предложения.
    • ThingA.DoSomethingToThingB (ThingB m) является неизбежной комбинацией, поскольку во всех языках, которые я могу придумать, функции принадлежат одному классу и не принадлежат взаимно Но это имеет смысл, потому что вы можете иметь субъект и объект.

Активный голос более прост, чем пассивный, поэтому убедитесь, что в вашем предложении есть тема, которая не просто «компьютер». Это означает, что используйте форму 1 и форму 3 часто, и используйте форму 2 редко.

Для наглядности:

// Form 1:  "File handle, close."
fileHandle.close(); 

// Form 2:  "(Computer,) close the file handle."
close(fileHandle);

// Form 3:  "File handle, write the contents of another file handle."
fileHandle.writeContentsOf(anotherFileHandle);
3 голосов
/ 17 сентября 2008

Если вы имеете дело с внутренним состоянием вещи, Thing.DoSomething () имеет больше смысла, потому что даже если вы измените внутреннее представление Thing или его работу, код, обращающийся к нему, не должен менять. Если вы имеете дело с коллекцией вещей или пишете какие-либо служебные методы, DoSomethingToThing () в процедурном стиле может иметь больше смысла или быть более понятным; но, тем не менее, обычно может быть представлен как метод для объекта, представляющего эту коллекцию: например

GetTotalPriceofThings();

против

Cart.getTotal();

Это действительно зависит от того, насколько объектно-ориентирован ваш код.

1 голос
/ 17 сентября 2008

Я согласен с Орионом, но я перефразирую процесс принятия решения.

У вас есть существительное и глагол / объект и действие.

  • Если многие объекты этого типа будут использовать это действие, попробуйте сделать действие частью объекта.
  • В противном случае попробуйте сгруппировать действие отдельно, но с соответствующими действиями.

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

Еще один способ думать об этом - это купить часть развлекательной системы. Имеет смысл объединить пульт дистанционного управления с телевизором, потому что вы всегда используете их вместе. Но было бы странно связывать кабель питания для конкретного видеомагнитофона с телевизором, так как многие клиенты никогда не будут использовать это. Ключевая идея как часто это действие будет использоваться для этого объекта ?

0 голосов
/ 17 сентября 2008

Я должен согласиться с Кевином Коннером

Также имейте в виду абонента любой из 2 форм. Вызывающий объект - это, вероятно, метод какого-то другого объекта, который определенно что-то делает с вашей вещью:)

0 голосов
/ 17 сентября 2008

Даже в объектно-ориентированном программировании может быть полезно использовать вызов функции вместо метода (или, в этом отношении, вызова метода объекта, отличного от того, для которого мы его вызываем). Представьте себе простую среду хранения базы данных, в которой вы хотите просто вызвать save () для объекта. Вместо включения оператора SQL в каждый класс, который вы хотите сохранить, что усложняет код, распределяет SQL по всему коду и делает изменение механизма хранения PITA, вы можете создать интерфейс, определяющий save (Class1), save (Class2 ) и т. д. и его реализация. Тогда вы на самом деле будете вызывать databaseSaver.save (class1) и хранить все в одном месте.

0 голосов
/ 17 сентября 2008

Чтобы добавить к ответу Aeon, это зависит от того, что вы хотите сделать и что с этим делать. Так что, если вы пишете Thing, а DoSomething изменяет внутреннее состояние Thing, тогда лучшим подходом является Thing.DoSomething. Однако, если действие делает больше, чем просто изменяет внутреннее состояние, то DoSomething (Thing) имеет больше смысла. Например:

Collection.Add(Thing)

лучше

Thing.AddSelfToCollection(Collection)

И если вы не написали Thing и не можете создать производный класс, то у вас нет выбора, кроме как делать DoSomething (Thing)

0 голосов
/ 17 сентября 2008

Если выполнение DoSomething с объектом может привести к другому результату в другом сценарии, то я бы предложил вам oneThing.DoSomethingToThing (anotherThing).

Например, у вас может быть два способа сохранения вещи в вашей программе, так что вы можете использовать DatabaseObject.Save (вещь). SaveToSession ().

Я редко передаю параметры в класс, если я не получаю открытые свойства.

0 голосов
/ 17 сентября 2008

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

Например, invoice.getTotal ()

Если «что-то» не является частью доменной модели «вещи», то одним из вариантов является использование вспомогательного метода.

Например: Logger.log (счет-фактура)

...