Подтвердить что ты не робот

Должны ли методы, которые должны выполняться в определенном порядке, являются частными?

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

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();
4b9b3361

Ответ 1

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

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

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

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

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


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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Что бы я сделал в этом случае, это примерно так:

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

MyObject myObject = new MyObject(); // make a constructor to take any parameters that are required to "setup" the object per your requirements.
myObject.UploadToWebService();

Ответ 7

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

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

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

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

Ответ 11

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

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

Ответ 12

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

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

if(preRetrieveHandlerExists){ preRetrieveHandler() } obj.RetrieveImages();

if(postRetrieveHandlerExists){ postRetrieveHandler() } //so on and so forth

Ответ 13

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

Ответ 14

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

Ответ 15

Fowler использует термин "зависть Feature", чтобы описать ситуацию, когда один объект вызывает несколько методов (особенно многократно) на другом.

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