мысли по настройке через делегатов - PullRequest
0 голосов
/ 04 января 2010

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

так в более общем сценарии,

дано:

class Foo {
    private parm1, parm2, ... , parmN
    public Foo(parm1, parm2, ... , parmN) {
        this.parm1 = parm1;
        this.parm2 = parm2;
        ...
        this.parmN = parmN;
    }

    public Bar DoWork() {
        var r = new externallyKnownResource();
        r.parm1 = parm1;
        r.parm2 = parm2;
        ...
        r.parmN = parmN;
        r.doStuff();
    }
}

сделать:

class Foo {
    private Action<externallyKnownResource> configurator;
    public Foo(Action<externallyKnownResource> configurator) {
        this.configurator = configurator;
    }

    public Bar DoWork() {
        var r = new externallyKnownResource();
        configurator(r);
        r.doStuff();
    }
}

последний кажется мне намного чище, но он подвергает воздействию внешнего мира, который class Foo использует externallyKnownResource

мысли

Ответы [ 3 ]

2 голосов
/ 04 января 2010

Это может привести к более чистому виду кода, но имеет огромный недостаток.

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

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

1 голос
/ 04 января 2010

Я могу что-то упустить здесь, но кажется большим недостатком создание объекта externallyKnownResource вниз в DoWork (). Это исключает простую замену альтернативной реализации. Почему бы и нет:

public Bar DoWork( IExternallyKnownResource r ) { ... }
0 голосов
/ 04 января 2010

IMO, вам лучше всего принять объект конфигурации в качестве одного параметра для вашего конструктора Foo, а не дюжину (или около того) отдельных параметров.

Редактировать:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...