Слой прикладной службы как статические классы

В моем приложении MVC ASP.NET у меня есть проект, который содержит всю бизнес-логику / уровень служб. Этот проект взаимодействует с моей Базой данных (Платформа объекта), который расположен в отдельном проекте.

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

 ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc..

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

    private static AllRepos _Repos;
    private static AllRepos Repos { 
       get 
        { 
           if(_Repos == null)
              _Repos = new AllRepos();

           return _Repos
        }
    }

    public static void CreateAccount(string username, password)
    {
        string salt = GenerateSalt();
        Account newAccount = DatabaseLayer.Models.Account
              { 
              Name = username,
              Password = HashPassword(password, salt),
              Salt = salt
              };
        Repos.AddAccount(newAccount);      
    }

Поскольку я не хотел делать следующее везде на моем уровне служб:

 AccountRepository Accounts = new DatabaseLayer.AccountRepository();

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

 public class AllRepos
 {

    private AccountRepository _Accounts;

    public AccountRepository Accounts
    {
        get
        {
            if (_Accounts== null)
                _Accounts= new AccountRepository();

            return _Accounts;
        }
    }

    // the same is done for every other repository (currently have about 10+)
  }

Который использовался в статических классах уровня служб.

Поскольку все мои классы уровня служб статичны и Repos поле также статично, очевидная проблема, с которой я продолжаю встречаться, - то, где тот же объект получен от нескольких datacontexts порождение странных поведений для обновлений/удалений.

Я понимаю, что это должно ожидаться, если я буду использовать статических участников/классы, как я сделал, так как они длятся жизненный цикл приложения, но есть ли способ быть в состоянии использовать уровень служб как ServiceLayer.Accounts.Method() не имея необходимость создавать нестатический класс, который нужно инстанцировать везде, это используется, и не встречаются с проблемами CRUD из-за нескольких datacontext экземпляров?

9
задан Omar 17 February 2010 в 19:41
поделиться

4 ответа

Несколько ответов привели примеры использования графиков (например, сетевое моделирование), и вы спросили: «Какое отношение это имеет к программированию?».

Ответ на этот вопрос заключается в том, что он не имеет большого отношения к программированию. Это связано с решением проблем.

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

-121--758422-

Я уже больше года использую CodeIgniter. По большей части мне это очень нравится (я участвую в форуме и использую его в каждом случае, который я могу), но я НЕНАВИЖУ ВЫСОКОМЕРИЕ этого утверждения в руководстве:

Разрушает глобальный массив GET. С тех пор CodeIgniter не использует GET последовательности, нет причин разрешать это.

Предположение, что в приложении CodeIgniter вам никогда не понадобится GET, - asinine! Уже через несколько дней мне пришлось иметь дело со страницами обратной публикации от PayPal и ClickBank (я уверен, что есть миллион других). Угадай что, они используют GET!!!

Есть способы остановить это squashing GET, но это вещи, которые имеют тенденцию портить другие вещи вверх. Что вы не хотите слышать, так это то, что вы должны перекодировать все свои представления, потому что вы включили строки запросов, и теперь ваши ссылки нарушены! Внимательно прочитайте руководство по этому варианту!

Один из них, который мне нравится (но не сработал, потому что настройка REQUEST_URI в config.php нарушила мой сайт), это расширение класса Input:

class MY_Input extends CI_Input
{
        function _sanitize_globals()
        {
            $this->allow_get_array = TRUE;
            parent::_sanitize_globals();
        }
}

Но лучший способ без всякой ерунды - проверить с помощью print_r ($ _ SERVER) по URL, где вам нужны переменные GET. Узнайте, какой параметр протокола URI отображает переменные GET и использует их.

В моем случае я вижу, что мне нужно в REQUEST_URI

// defeat stupid CI GET squashing!
parse_str($_SERVER['REQUEST_URI'], $_GET);

This помещает последовательность запроса обратно в суперглобальный $ _ GET для этого экземпляра страницы (Вы не должны использовать $ _ GET, это может быть любая переменная.)

EDIT

После публикации я обнаружил, что при использовании REQUEST_URI вы потеряете свой первый запрос последовательности ключ массива, если вы не удалите все до?. Например, URL-адрес, как/controller/method? one = 1 & two = 2, заполнит массив $ _ GET в этом примере массивом ('method? one' = > 1, 'два' = > 2). Чтобы обойти это, я использовал следующий код:

parse_str(substr(strrchr($_SERVER['REQUEST_URI'], "?"), 1), $_GET);

Я полагаю, я должен был предоставить пример, так что здесь:

class Pgate extends Controller {
   function postback() {
      parse_str(substr(strrchr($_SERVER['REQUEST_URI'], "?"), 1), $_GET);
      $receipt = $this->input->xss_clean($_GET['receipt']);
   }
}
-121--2519089-

Ваш подход к этому действительно не рекомендуется. Лично я бы никогда не допустил такого подхода в своей команде. Недостатки:

  1. Основные проблемы многопоточности, как вы испытываете, которые не просто решить
  2. Вы не можете проверить это очень легко.
  3. Нереалистичная абстракция доступа к данным

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

В любом случае следует просто создать экземпляр репозитория как часть классов базовых служб. Нет причин, по которым это должен быть «статический ИЛИ вызов экземпляра везде». Внутри базовых классов должен быть ограничен код экземпляра.

15
ответ дан 4 December 2019 в 09:12
поделиться

Я не уверен, почему вы так категорически против использования экземпляров. Помимо того факта, что код, который у вас сейчас есть, излишне сложен, использование статических типов также затрудняет модульное тестирование. Статический тип похож на синглтон, который вы не можете имитировать / заменить. Мне кажется, что ваш настоящий вопрос может заключаться в следующем: «Как мне управлять экземплярами уровня сервиса в течение всего срока службы?» Как правило, вы делаете это, имея один экземпляр на каждый веб-запрос. В приложении ASP.NET MVC вы можете создать новый контейнер DI через ControllerFactory и обрабатывать все это. [PDF]

10
ответ дан 4 December 2019 в 09:12
поделиться

Вы должны осознанно обрабатывать область контекста объекта, как, например, при использовании шаблона Unit Of Work

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

Я могу сказать это, поскольку раньше обгорел себя, делая подобные вещи:)

1
ответ дан 4 December 2019 в 09:12
поделиться

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

-3
ответ дан 4 December 2019 в 09:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: