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


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.