С точки зрения твердых принципов ответ jgauffin имеет смысл. Однако не стоит забывать об общих принципах проектирования, например, сокрытии информации .
Я вижу несколько проблем с данным подходом:
- Как вы сами указали, люди не ожидают использовать ключевое слово «new», когда созданный объект не управляет каким-либо состоянием . Ваш дизайн отражает его намерения. Люди, использующие ваш класс, могут запутаться в том, какое состояние он управляет, и могут ли последующие вызовы метода привести к другому поведению.
- С точки зрения человека, использующего класс, внутреннее состояние хорошо скрыто, но когда вы хотите внести изменения в класс или просто понять его, вы делаете вещи более сложными. Я уже много писал о проблемах, которые я вижу с методами разделения, просто чтобы уменьшить их , особенно при перемещении состояния в область видимости класса. Вы изменяете способ использования вашего API только для того, чтобы иметь меньшие функции! Это, на мой взгляд, определенно заходит слишком далеко.
Некоторые связанные ссылки
Возможно, главный аргумент заключается в том, как далеко простирается принцип единой ответственности . «Если вы доведите это до крайности и соберете классы, у которых есть одна причина существования, у вас может получиться только один метод на класс. Это приведет к большому разрастанию классов даже для самых простых процессов, в результате чего система будет трудно понять и трудно изменить ".
Другая важная ссылка, относящаяся к этой теме: «Разделите ваши программы на методы, которые выполняют одну идентифицируемую задачу. Сохраните все операции в методе на одном уровне абстракции » - Кент Бек Кей здесь "тот же уровень абстракции". Это не означает «одна вещь», как это часто интерпретируется. Этот уровень абстракции полностью зависит от контекста, для которого вы разрабатываете.
Так каков правильный подход?
Не зная вашего конкретного варианта использования, трудно сказать. Есть сценарий, в котором я иногда (не часто) использую подобный подход. Когда я хочу обработать набор данных, не желая делать эту функциональность доступной для всей области видимости класса. Я написал в блоге об этом, как лямбда может еще больше улучшить инкапсуляцию . Я также начал вопрос по теме здесь на программистов . Ниже приведен последний пример использования этой техники.
new TupleList<Key, int>
{
{ Key.NumPad1, 1 },
...
{ Key.NumPad3, 16 },
{ Key.NumPad4, 17 },
}
.ForEach( t =>
{
var trigger = new IC.Trigger.EventTrigger(
new KeyInputCondition( t.Item1, KeyInputCondition.KeyState.Down ) );
trigger.ConditionsMet += () => AddMarker( t.Item2 );
_inputController.AddTrigger( trigger );
} );
Поскольку сам «локальный» код внутри ForEach
не используется повторно нигде, я могу просто сохранить его в точном месте, где он имеет значение. Изложение кода таким образом, что код, опирающийся друг на друга, сильно сгруппирован, делает его более читабельным, на мой взгляд.
Возможные альтернативы
- В C # вы можете использовать вместо этого методы расширения. Поэтому оперируйте аргументом непосредственно, передавая этот метод «одно».
- Посмотрите, действительно ли эта функция не принадлежит другому классу.
- Сделайте это статической функцией в статическом классе . Скорее всего, это наиболее подходящий подход, который также отражен в общих API, на которые вы ссылались.
bool arrayContainsSomestring = new List<string>(stringArray).Contains("somestring");
когда все, о чем я заботился, - это конкретная часть информации, а методы расширения LINQ недоступны. Работает нормально, и вписывается вif()
условия без необходимости прыгать через обручи. Конечно, вам нужен язык для сбора мусора, если вы пишете такой код.