Должен ли длинный метод использоваться только один раз в своем классе или в функции? - PullRequest
1 голос
/ 14 декабря 2008

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

 class iOnlyHaveOneMethod{
   public function theOneMethod(){
     //loads and loads of code, say 100's of lines
     // but it only gets used once in the whole application
   }
 }

 if($foo){ 
  $bar = new iOnlyHaveOneMEthod;
  $bar->theOneMethod();
 }

Это действительно лучше, чем:

if($foo){
 //loads and loads of code which only gets used here and nowhere else
}


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

function loadsAndLoadsOfCode(){
 //Loads and loads of code
}
if($foo){ loadsAndLoadsOfCode(); }

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

Ответы [ 10 ]

8 голосов
/ 14 декабря 2008

Проблема не в том, находится ли она в функции или объекте.

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

Что делают эти сотни строк? Это то место, где стоит искать реализацию объектно-ориентированного передового опыта.

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

4 голосов
/ 14 декабря 2008

Что ж, если в методе действительно есть «загрузки и загрузки» кода, то его следует разбить на несколько защищенных методов в этом классе, и в этом случае использование области видимости класса оправдано.

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

2 голосов
/ 14 декабря 2008

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

// let's instead assume that $bar was set earlier using a setter
if($foo){ 
    $bar = getMyBar();
    $bar->theOneMethod();
}

Это дает вам пару преимуществ:

  • Это простой пример паттерна стратегии . если $bar реализует интерфейс, обеспечивающий theOneMethod(), то вы можете динамически переключать реализации этого метода;

  • Тестирование вашего класса независимо от $bar->theOneMethod() значительно проще, так как вы можете заменить $bar макетом во время тестирования.

Ни одно из этих преимуществ недоступно, если вы просто используете статическую функцию.

Я бы сказал, что, хотя простые статические функции имеют свое место, нетривиальные методы (как ясно из «сотен строк») в любом случае заслуживают своего собственного экземпляра:

  • для разделения проблем;
  • , чтобы помочь тестированию;
  • , чтобы помочь рефакторингу и повторной реализации.
1 голос
/ 14 декабря 2008

Вы действительно задаете два вопроса здесь:

  • Разве лучше объявить функцию, чем создать объект, содержащий только эту функцию?
  • Должна ли какая-либо функция содержать «загрузки кода»?

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

Вторая часть: в идеале нет, но нет четкого определения «нагрузок», и в некоторых случаях это может быть уместно.

0 голосов
/ 14 декабря 2008

Для тестируемости, безусловно, лучше разбить его на отдельный класс с отдельными методами. Намного проще писать модульные тесты для отдельных методов, чем как часть встроенного оператора if в файле с выделенным кодом или еще много чего.

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

0 голосов
/ 14 декабря 2008

Думаю, я бы перефразировал вопрос, который вы задаете. Я думаю, что вы хотите задать вопросы, мой класс поддерживает принцип одиночной ответственности . Есть ли в любом случае разделить части вашего класса на отдельные меньшие части, которые могут меняться независимо друг от друга (доступ к данным и их разбор и т. Д.). Можете ли вы легко протестировать свой класс? ,

Если вы можете сказать «да» вышеупомянутым пунктам, я не буду беспокоиться о методе по сравнению с новым классом, поскольку весь смысл в том, что у вас есть читабельный, поддерживаемый код.

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

0 голосов
/ 14 декабря 2008

Столько, сколько один метод с большим количеством кода - это запах кода. Моей первой мыслью было, по крайней мере, сделать метод статичным. В классе нет данных, поэтому нет необходимости создавать объект.

0 голосов
/ 14 декабря 2008

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

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

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

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

0 голосов
/ 14 декабря 2008

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

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

0 голосов
/ 14 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...