2013-03-12 2 views
2

Есть методы, которые возвращают void, но изменяют состояние своих аргументов (т. Е. Предоставляют скрытое или неявное возвращаемое значение), как правило, плохая практика?Недействительные методы возврата, которые изменяют состояние их аргумента как анти-шаблон?

Мне кажется, что их сложно насмехаться, что предполагает, что они, возможно, являются признаком плохого дизайна.

Какие шаблоны существуют для их устранения?

Очень надуманный пример:

public interface IMapper 
{ 
    void Map(SourceObject source, TargetObject target); 
} 

public class ClassUnderTest 
{ 
    private IMapper _mapper; 

    public ClassUnderTest(IMapper mapper) 
    { 
     _mapper = mapper; 
    } 

    public int SomeOperation() 
    { 
     var source = new SourceObject(); 
     var target = new TargetObject(); 

     _mapper.Map(source, target); 

     return target.SomeMappedValue; 
    } 
} 
+0

Как насчет метода void Initialize(), который возвращает void и существует только с целью изменения состояния объекта? Или void Fill (объект o), который выполняет какое-либо действие над объектом o? Тип возврата не имеет корреляции с внутренним состоянием и аргументами. Семантика метода должна четко указывать, будет ли изменено состояние или аргументы. Если метод делает что-то большее, что он предназначен, то это анти-шаблон. Это более чистое кодирование. –

+0

Это именно то, во что я ехал - семантика не ясна или, по крайней мере, путается в этих случаях. – MalcomTucker

ответ

1

Да в некоторой степени.

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

Решение заключается в программном обеспечении без побочных эффектов. Это означает, что вы не меняете переменные, поля или что-то еще. Вместо этого вы вернете новую версию того, что вы обычно меняете.

Это основной принцип функционального программирования.

Конечно, этот способ программирования имеет свои собственные проблемы. Просто рассмотрите ввод-вывод.

1

Ваш код whould будет намного проще, чтобы проверить, если вы сделаете это:

public interface IMapper 
{ 
    TargetObject Map(SourceObject source); 
} 

public class ClassUnderTest 
{ 
    private IMapper _mapper; 

    public ClassUnderTest(IMapper mapper) 
    { 
     _mapper = mapper; 
    } 

    public int SomeOperation(SourceObject source) 
    { 
     var target = _mapper.Map(source, target); 
     return target.SomeMappedValue; 
    } 
} 

Теперь вы можете проверить вас Карта opperation и SomeOperation seperatly. Проблема в том, что вы можете изменить состояние объекта, что затрудняет предоставление заглушки для тестирования. При возврате нового объекта вы можете вернуть тестовый заглушка цели и протестировать свой метод вызова.

+0

Да, абсолютно, изменение выше совершенно тривиально. Но иногда вы не можете легко изменить API. Мой вопрос в том, считают ли люди этот тип рисунка плохим дизайном ... – MalcomTucker

+0

Если вы не можете его протестировать, это плохой дизайн. Это все о написании проверяемого кода. И если это можно проверить, это гораздо легче понять. – Peter

Смежные вопросы