Запах кода, если закрытый метод вызывает публичный?

25

Запах кода вызывать публичный метод в приватном методе того же экземпляра объекта?

Eimantas
источник
AAMOI у вас есть конкретный пример?
ocodo
Нет не сейчас Просто вспомнил случай, который я обсуждал со своими коллегами. Хотелось также получить некоторые мнения здесь.
Eimantas
5
Обычно я могу определить аббревиатуру по контексту, но в AAMOI мне определенно приходилось искать
Карсон Майерс
@ Карсон - ты что-нибудь нашел?
Eimantas
4
Как вопрос интереса
Карсон Майерс

Ответы:

32

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

Фанат
источник
Я согласен. Некоторые методы предоставляют функциональность, которая полезна как для внутренних, так и для внешних абонентов. Красный флаг может быть, если открытый метод очень специфичен для внутренней реализации, но даже в этом случае не каждый класс предназначен для сокрытия своих внутренних объектов. Например, у меня часто есть слой «инструмента» структуры данных под слоем абстрактного типа контейнера - так я могу повторно использовать часть кода структуры данных для других структур данных, лежащих в основе других контейнеров.
Steve314
19

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

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

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

Как и для всех запахов кода, это мотивация для дальнейшей проверки кода, рационализации и, возможно, рефакторинга, но не повод для тревоги.

ocodo
источник
5
+1 за «не повод для тревоги». Слишком много раз мы видим «запах» и мгновенно переходим в режим рефакторинга, не задумываясь.
Майкл К
+1 за ПСП. Я просто наткнулся на случай, когда декоратор не работал, потому что декорированный класс вызывал свою собственную публичную функцию, минуя декоратор. Решение: разбить класс на две части и добавить декорированную зависимость.
Джон Халка
18

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

Ким
источник
Зачем? Если перезаписанный публичный метод приводит к неприятным сюрпризам, действительно ли имеет значение, кто вызвал этот метод?
user281377
4
Да, это так. Если переопределение одного открытого метода нарушает другой открытый метод, я также могу переопределить этот другой метод. Если это сломает частный метод, я могу ....?
Ким
5
Неприятный сюрприз, возникающий из-за переопределения публичного метода, - сам по себе запах кода. На самом деле, зловоние кода.
Ларри Коулман
Ким: если метод общедоступен, вы должны предположить, что другие классы также вызывают этот метод ...
user281377
@Larry: точно! Закрытый метод (который обычно содержит предположения, относящиеся к реализации), вызывающий открытый, повышает вероятность того, что переопределение открытого метода приведет к поломке.
Ким
5

Я не думаю, что мы можем обобщать.

Все очень сильно зависит от контекста.

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

Нивы
источник
5

Нет. Что еще нужно сделать в этом случае? Сделать приватный метод общедоступным или публичный метод частным? Скопировать и вставить код из открытого метода в приватный?

user281377
источник
Или попросите делегировать открытый метод (новому) приватному методу, который вызывается другим приватным методом. Но зачем?
Лоуренс Дол
4

Нет , здесь нет неприятного запаха.

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

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

Отображаемое имя
источник
2

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

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

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

  3. Более вероятно, чтобы ввести круговые ошибки и бесконечные циклы и исключения из памяти, на мой взгляд.

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

Марк Грэм
источник
1
Что если существующий публичный метод вызывается многими другими классами? Сделав это приватным, это сломается. Помните, что публичные методы вызываются другими классами по другим причинам, а не только по этому классу. вроде почему существуют публичные методы.
Майкл Даррант
Я заявил, что «содержимое открытого метода должно быть взято и помещено в закрытый метод ...» Открытый метод останется, но вызовет новый закрытый метод. Как и любые другие частные методы, которые должны повторно использовать те же функции.
Марк Грэм
Таким образом, вы добавляете другой метод ни по какой другой причине, кроме - ну, потому что вы объявили, что это «запах кода». Бессмысленные методы - худший запах кода.
gnasher729
Извините, но я не просто перечислил несколько причин выше. Большая часть кода, который я пишу, предназначена для бизнес-систем, многие классы ограничены пользователями на основе ролей. Многие публичные методы проверяют пользовательские права и параметры. С какой стати я хотел бы отозвать тот же общедоступный метод, чтобы повторно использовать его функциональность и повторно протестировать пользовательские разрешения?
Марк Грэм,
Мне никогда не приходилось вызывать публичный метод из частного. Это только кажется и кажется мне очень неправильным. Я действительно удивлен, большинство людей думают, что все в порядке.
Ловушка
2

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

  • Создать дублированный приватный метод? нет
  • Создать специальный публичный метод для случая? нет
  • Вызовите специальный закрытый метод, который может вызывать публичные методы? нет
  • Какой-то супер, который может это сделать? нет

Ответ очевиден: если вам нужна функциональность открытого метода, вы должны иметь возможность вызывать этот метод из методов этого класса или из других классов.

Майкл Даррант
источник
1

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

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

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

Нил
источник
1

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

(а) публично раскрыть что-то, что должно быть частным; или

(б) поведение класса недостаточно узкое (подумайте о принципе единой ответственности).

Брэд Томас
источник