Почему считается, что этот код нарушает Закон Деметры?

Вот метод из моего приложения для Android:

public ViewHolderBase buildView(PlayerResult playerResult)
{
    View result = inflater.inflate(
        R.layout.player_result,
        null);
    this.helper = new ViewHelper(result);

    ViewHolderBase holder = createViewHolder();

    TextView playerName = helper.findTextView(R.id.playerName);
    holder.setPlayerNameTextView(playerName); // <-- alleged violation

    TableLayout tableLayout = helper.findTableLayout(R.id.tlPossibleResults);
    populateTableLayout(holder, tableLayout, playerResult);
    holder.setView(result); // <-- another one
    return holder;
}

Android Studio «считает», что эти две строчки нарушают закон Деметры:

holder.setPlayerNameTextView(playerName);
holder.setView(result);

Я не понимаю. Вот определение:

Закон Деметры для функций требует, чтобы метод m объекта O мог вызывать только методы следующих типов объектов:

  • О сам
  • параметры m
  • Любые объекты, созданные / экземпляры в пределах m
  • Объекты прямого компонента O
  • Глобальная переменная, доступная для O, в области m

Так? holder переменная создается / создается в m.

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

Это не для IDE - если вместо этого я создаю экземпляр holder, предупреждения все равно будут отображаться.

Вопрос:

Android Studio ошибается? Или мое понимание Закона Деметры отсутствует? Если последнее верно, как мне провести рефакторинг этого бита для удовлетворения требований LoD?


person Konrad Morawski    schedule 12.01.2014    source источник
comment
Насколько я понимаю, в этих двух строках нет ничего плохого.   -  person Don Roby    schedule 12.01.2014
comment
Можете ли вы показать, пожалуйста, метод createViewHolder или указать класс, реализующий createViewHolder.   -  person Diversity    schedule 12.01.2014
comment
@Diversity - createViewHolder является абстрактным в этом классе (я использую шаблон абстрактного метода). Он переопределяется в производном классе, и его реализация однострочная: return new RangeViewHolder();. Но, как я уже сказал, даже если я заменю createViewHolder прямым встроенным экземпляром (= new RangeViewHolder()), предупреждения останутся   -  person Konrad Morawski    schedule 12.01.2014


Ответы (1)


Фактически ни один из объектов не создается в «m»; и держатель, и результат являются возвращаемым значением функции, так что технически объект, который был создан в другом месте.

Конечно, вы знаете, что createViewHolder просто создает объект для использования кем-то другим, и я предполагаю, что то же самое верно и для inflater.inflate; так что вы, вероятно, можете не рассматривать их как ложные срабатывания. Но невозможно программно сообщить об этом аналитическому программному обеспечению, поэтому я предполагаю, что именно поэтому вы получаете предупреждения.

Одно замечание: поскольку вы делегируете createViewHolder дочернему классу, вы открываете себе код; таким образом, я бы все равно назвал это нарушением Закона Деметры. На мой взгляд, это не значит, что ваш код плохой.

person Calimar41    schedule 25.03.2014