Должны ли методы, которые должны выполняться в определенном порядке, быть закрытыми? [закрыто]

У меня есть класс, который извлекает некоторые данные, а изображения делают с ними что-то, и они загружают их в стороннее приложение, используя веб-сервисы. Объект должен выполнить несколько определенных шагов по порядку. Мой вопрос заключается в том, должен ли я публично разоблачать каждый метод публично, вот так.

myObject obj = new myObject();
obj.RetrieveImages();
obj.RetrieveAssociatedData();
obj.LogIntoThirdPartyWebService();
obj.UploadStuffToWebService();

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

public class myObject()
{
 private void RetrieveImages(){};
 private void RetrieveAssociatedData(){};
 private void LogIntoThirdPartyWebService(){};
 private void UploadStuffToWebService(){};

 public void DoStuff()
  {
   this.RetrieveImages();
   this.RetrieveAssociatedData();
   this.LogIntoThirdPartyWebService();
   this.UploadStuffToWebService();
  }
}

который называется так.

myObject obj = new myObject();
obj.DoStuff();
c#
26 голосов | спросил etoisarobot 28 PMpWed, 28 Apr 2010 18:59:40 +040059Wednesday 2010, 18:59:40

15 ответов


0

Это зависит от того, кто знает, что методы должны вызываться таким образом.

  • Потребитель знает: Например, если объектом является Stream, обычно это потребитель потока решает, когда Open, Read и Close поток. Очевидно, что эти методы должны быть публичными, иначе объект не может быть использован должным образом. (*)

  • Объект знает: Если объект знает порядок методов (например, это TaxForm и должен выполнять вычисления в определенном порядке), тогда эти методы должны быть закрытыми и доступны через один шаг более высокого уровня (например, ComputeFederalTax вызовет CalculateDeductions, AdjustGrossIncome и DeductStateIncome).

  • Если количество шагов больше, чем несколько, вам нужно рассмотреть Strategy вместо наличия шагов соединены непосредственно в объект. Затем вы можете изменить положение вещей, не перегружая объект или его интерфейс.

В вашем конкретном случае не похоже, что потребитель вашего объекта заботится о чем-либо, кроме выполняемой операции обработки. Поскольку ему не нужно знать порядок, в котором эти шаги выполняются, должен быть только один открытый метод с именем Process (или что-то на этот счет).


(*) Однако обычно объект знает, по крайней мере, порядок , в котором можно вызывать методы для предотвращения недопустимого состояния, даже если он не знает, когда На самом деле делать шаги. То есть объект должен знать достаточно, чтобы не попасть в бессмысленное состояние; выдает какое-то исключение, если вы пытаетесь вызвать Close перед Open хороший пример этого.

ответил John Feminella 28 PMpWed, 28 Apr 2010 19:02:49 +040002Wednesday 2010, 19:02:49
0

Если метод B () действительно не может быть вызван до тех пор, пока A () не будет вызван первым, то правильный дизайн требует, чтобы A возвращал некоторый объект, который B требует в качестве параметра.

Всегда ли это практично, это другой вопрос, но именно так следует сделать.

ответил Rex M 28 PMpWed, 28 Apr 2010 19:23:59 +040023Wednesday 2010, 19:23:59
0

Да, конфиденциально, в противном случае вы оставляете дверь открытой для пользователей, которые делают что-то не так, что будет только причиной боли для всех.

Вам когда-нибудь нужно вызывать какой-либо из этих методов самостоятельно? то есть кто-нибудь из них делает что-нибудь полезное и может понадобиться в одиночку? если это так, то вы можете захотеть сделать их общедоступными, но даже если вы сделаете их все публичными, у вас должен быть метод, который вызывает их в правильном порядке (желательно с полезным именем), чтобы упростить работу для ваших пользователей.

ответил Sam Holder 28 PMpWed, 28 Apr 2010 19:01:14 +040001Wednesday 2010, 19:01:14
0

Все зависит от того, является ли операция по существу атомарной. В этом случае для нас, посторонних, это выглядит как одна операция, но так ли это на самом деле? Если LogIntoThirdPartyWebService завершится неудачно, нужно ли в пользовательском интерфейсе открыть диалоговое окно, чтобы спросить пользователя, не хотят ли они повторить попытку? В случае, когда у вас есть одна операция, повторная попытка операции LogIntoThirdPartyWebService также требует повторного выполнения потенциально дорогих операций, таких как RetrieveImages, в то время как их разделение обеспечивает более детальную логику.

В этом случае я бы сделал что-то вроде этого:

Images images = RetrieveImages();
ImagesAndData data = RetrieveAssociatedData(images);
WebService webservice = LogIntoThirdPartyWebService();
UploadStuffToWebService(data, webservice);

или, может быть, в идеале что-то вроде этого:

UploadStuffToWebService(RetrieveImages().RetrieveAssociatedData(),
                        LogIntoThirdPartyWebService());

Теперь у вас есть гранулярность при соблюдении правильного порядка операций.

ответил Gabe 28 PMpWed, 28 Apr 2010 19:14:11 +040014Wednesday 2010, 19:14:11
0

Для меня это звучит как с точки зрения потребителя вашего объекта, объект делает одно: он перемещает изображения из одного места в другое. Как потребитель объекта, все отдельные шаги, которые вы должны предпринять, чтобы выполнить, которые не имеют отношения к мне; В конце концов, вот почему я должен сделать это для меня.

Таким образом, у вас должен быть один метод DoStuff(), который принимает все необходимые параметры и делает все детали реализации закрытыми.

ответил i_am_jorf 28 PMpWed, 28 Apr 2010 19:02:11 +040002Wednesday 2010, 19:02:11
0

Закрытый - и взять параметры в конструкторе и выполнить там заказ.

Не думайте, что вызывающий абонент будет или знает, как его вызвать, по порядку.

Итак, вместо приведенного вами примера я бы сделал это следующим образом:

MyObject myObject = new MyObject(); // make a constructor to take any parameters that are required to "setup" the object per your requirements.
myObject.UploadToWebService();
ответил Ian P 28 PMpWed, 28 Apr 2010 19:01:00 +040001Wednesday 2010, 19:01:00
0

Это действительно зависит от того, оцените ли вы, что кто-то захочет вызвать только один из этих методов, и имеют ли они смысл по отдельности или могут быть реализованы независимо. Если нет, то лучше избегать разоблачения чего-либо, кроме операции высокого уровня.

ответил Uri 28 PMpWed, 28 Apr 2010 19:02:15 +040002Wednesday 2010, 19:02:15
0

Предоставьте как можно меньше информации, насколько это необходимо. Если вызов FuncA() равен всегда с последующим вызовом FuncB(), сделать один public и пусть он вызывает другой, или же public FuncC() вызовите их последовательно.

ответил egrunin 28 PMpWed, 28 Apr 2010 19:02:45 +040002Wednesday 2010, 19:02:45
0

Да, он определенно должен быть закрытым, тем более что все методы кажутся беспараметрическими, а вы просто озабочены порядком.

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

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

ответил froadie 28 PMpWed, 28 Apr 2010 19:03:20 +040003Wednesday 2010, 19:03:20
0

Вопрос публичного или частного характера полностью зависит от контракта, который вы хотите выставить для своего объекта. Вы хотите, чтобы пользователи вашего объекта вызывали методы по отдельности, или вы хотите, чтобы они вызывали один метод "DoStuff" и покончили с ним?

Это все зависит от предполагаемого использования класса.

В приведенном вами примере я бы сказал, что DoStuff должен быть общедоступным, а остальные - частными.

ответил Randolpho 28 PMpWed, 28 Apr 2010 19:02:27 +040002Wednesday 2010, 19:02:27
0

Как вы думаете, что будет проще для потребителей вашего класса?

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

ответил Michael Todd 28 PMpWed, 28 Apr 2010 19:02:45 +040002Wednesday 2010, 19:02:45
0

Ни. Я думаю, что у вас есть по крайней мере 3 объекта, в противном случае вы нарушаете принцип единой ответственности. Вам нужен объект, который «получает и хранит изображения», тот, который «манипулирует изображениями», и тот, который «управляет взаимодействием с внешним поставщиком».

ответил DancesWithBamboo 28 PMpWed, 28 Apr 2010 19:39:21 +040039Wednesday 2010, 19:39:21
0

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

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

 

если (preRetrieveHandlerExists) {   preRetrieveHandler () } obj.RetrieveImages ();

если (postRetrieveHandlerExists) {   postRetrieveHandler () } //и так далее, и так далее

ответил frankc 28 PMpWed, 28 Apr 2010 19:23:24 +040023Wednesday 2010, 19:23:24
0

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

ответил Brandi 28 PMpWed, 28 Apr 2010 22:15:35 +040015Wednesday 2010, 22:15:35
0

Фаулер использует термин «Зависть к функциям» для описания ситуации, когда один объект вызывает несколько методов (особенно многократно) для другого.

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

ответил Jason 29 AMpThu, 29 Apr 2010 01:08:36 +040008Thursday 2010, 01:08:36

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132