Лучшие практики по дублированию кода c # - PullRequest
3 голосов
/ 26 февраля 2009

Я пытаюсь структурировать свой код таким образом, чтобы уменьшить / избежать дублирования кода, и я столкнулся с интересной проблемой. Каждый раз, когда мой код вызывает сохраненный процесс, мне нужно передать несколько переменных, которые являются общими для хранимого процесса: например, имя пользователя, домен, server_ip и client_ip. Все они происходят из объекта HttpRequest или объекта system.environment.

Так как они передаются каждому хранимому процессу, я сначала хотел создать служебный класс, который является оберткой базы данных и будет инициализировать и передавать их каждый раз, поэтому мне не нужно делать это в моем коде. Проблема в том, что класс c # (внутри папки App_Code) не видит объект Httprequest. Конечно, я мог бы передать это в качестве аргумента для оболочки, но это разрушило бы всю цель создания оболочки. Я что-то здесь упускаю?

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

Ответы [ 7 ]

4 голосов
/ 26 февраля 2009

Настройте слой данных для наследования от базового класса, который содержит 4 свойства для этих значений. Чтобы общедоступный конструктор требовал этих 4 свойств.

Затем сделайте нечто похожее на бизнес-уровне - базовый класс с этими 4 свойствами в конструкторе.

Затем пользовательский интерфейс создает новый BusObj (Запрос ["имя пользователя"], ...) .method ()

В слое данных у вас может быть метод, который создает массив SQLParameter с этими 4 свойствами, тогда каждый метод может добавлять дополнительные параметры в массив.

3 голосов
/ 26 февраля 2009

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

Еще одна вещь, на которую стоит обратить внимание: у вас есть методы, которые принимают большое количество параметров (4 - хорошее эмпирическое правило, но оно определенно индивидуально), пришло время заставить этот метод взять объект в качестве параметра вместо отдельных параметров. 99,99999999999999999999% времени такой объект должен быть неизменным (нет доступных для записи переменных экземпляра).

2 голосов
/ 26 февраля 2009

Вот странная идея, которая вам может или не может понравиться: определить класс 'profile' и функцию, которая расширяет профиль в аргументы функций, принимающих общие аргументы.

class P {
    readonly string name;
    readonly string domain;
    public P(string name, string domain) {
        this.name = name; this.domain = domain;
    }
    public void inject(Action<string, string> f) {
        f(p.arg1, p.arg2);
    }
    public T inject<T>(Func<string, string, T> f) {
        return f(p.arg1, p.arg2);
    }
}

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

2 голосов
/ 26 февраля 2009

HttpContext.Current содержит информацию, аналогичную той, что вы найдете в HttpRequest, и, что более важно, доступна внутри App_Code.

1 голос
/ 26 февраля 2009

Возможно, вы движетесь вниз по скользкому склону. Смысл в СУХОЙ состоит в том, чтобы не повторять бизнес-логику в нескольких местах, где изменение требований создает необходимость изменения кода в нескольких похожих местах. Вы не обязательно рефакторинг только потому, что 4 строки одинаковы, если эти 4 строки зависят от контекста. Вы также нарушили инкапсуляцию, сославшись на httprequest, так как используете глобальную переменную. Как потребителю вашего класса, я должен был бы знать детали реализации, которые я мог бы вызывать только из веб-приложения.

Это, как говорится, если вы принимаете это во внимание и все еще хотите продолжить, вот еще один вариант для получения информации, подобной этой. Создайте пользовательский SecurityPrincipal (Implement IPrincipal), который содержит нужные вам свойства, и присоедините его к потоку. Заполните их, когда пользователь войдет в систему, и вы сможете получить к нему доступ в любом месте во время запроса. Ваш абонент все еще должен убедиться, что это сделано, но, по крайней мере, это не зависит от платформы.

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

1 голос
/ 26 февраля 2009

Попробуйте System.Web.HttpContext.Current.Request, чтобы получить текущий запрос.

1 голос
/ 26 февраля 2009

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

Что касается использования HttpContext вместо этого, как предлагали некоторые другие, я бы сказал, что это плохая идея. Как только вы начинаете вводить зависимости в своем домене с помощью HttpContext, его очень трудно устранить. Что если позже вы захотите использовать свой модуль без HttpContext? А как насчет юнит-тестирования?

...