Поля и аргументы метода [закрыто]


9

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

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

Я хотел бы услышать ваше мнение о том, что вы думаете об этом компромиссе, и как вы решаете, какой подход выбрать в какой ситуации?

Поскольку при описании кода код зачастую проще для понимания, чем английский, я создал небольшую суть, в которой есть оба варианта: https://gist.github.com/JeroenDeDauw/6525656


Аргументы, которые используются только как локальные переменные (не глобальные для времени жизни объекта), должны находиться в области видимости только до тех пор, пока это имеет смысл ... Я нахожу это очень раздражающим, когда разработчики хранят неэкземплярное состояние как состояние экземпляра, потому что это удобно ... только мое мнение, хотя. Трудно увидеть, как на самом деле поток выполнения.
— Макс

Используя параметры и позволяя классу позаботиться о том, придется ли ему изменять состояние при выполнении метода, он прекрасно связан с принципом «не говори» . Просто имейте в виду, что функция Tell not ask не означает, что вы не можете запросить объект о его состоянии ( явная пробка )
— Marjan Venema

Ответы:


2

Поскольку единственный внешне видимый метод в вашем примере - это updateTable, я думаю, что лучше использовать поля вместо параметров метода.

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

Пример псевдокода:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

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


7

Использование полей позволяет использовать многопоточность для методов, использующих эти поля.

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


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

7

По словам непрофессионала:

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

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


1

Не используйте поля в текущем случае! Два «потока», использующих объект одновременно, будут сильно путать друг друга. Они также не должны быть реальными, отдельными потоками (отсюда и цитаты). Если вы устанавливаете объект для одной таблицы, затем вызываете метод, который использует его для другой таблицы, а затем пытаетесь использовать исходную настройку, у вас возникла проблема. Палка с параметрами на данный момент.

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


0

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

В этом случае мы должны руководствоваться не эффективностью (в любом случае разница незначительна) или (не дай Бог!) Легкостью печатания, а понятностью и естественностью кода.


0

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

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

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

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

Вы можете отменить и действие, но не функцию .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.