Дизайн класса с N-уровневой архитектурой - PullRequest
0 голосов
/ 18 апреля 2009

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

Предыдущий вопрос

У меня есть веб-приложение, которое было разделено на два проекта:

1) Сайт ASP.NET 2) DLL, содержащая объекты бизнес, методы логического уровня и методы DAL. Они разделены на разные пространства имен, но все в одной и той же DLL.

Чем больше я смотрел на это и расширял разработку, тем больше осознавал, что очень сильно иду по неверному пути. Я хотел разделить их на отдельные библиотеки DLL, чтобы иметь четкое разделение обязанностей.

Как только у меня был код в разных DLL, я понял, что многие классы вызывают друг друга. Например, когда объекты списка клиентов были созданы в DAL, он также вызывал бы companyDAL.cs и получал список компаний, к которым принадлежали клиенты. Так что теперь у меня было два класса, которые напрямую ссылались друг на друга. Это кажется довольно плохой вещью! Пахло плохо, но я продолжал и пытался отделить вещи, где мог.

С этой целью я вывел все объекты на интерфейсы и изменил все ссылки на них на интерфейс.

Я надеялся использовать какой-то DI (просто узнал об этом в данный момент), поэтому для каждого объекта я создал конструктор, который использовал Factory для этой DLL (эта фабрика создаст новый экземпляр каждого объекта, который класс может потребовать). Я также поместил конструктор по умолчанию, который вызвал бы конструктор DI с фабрикой по умолчанию, чтобы гарантировать, что всегда использовалась одна фабрика.

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

Factory
{
   IClient CreateNewIClient()
   {
         return new Client();
   }

   ICompany CreateNeIwCompany()
   {
          return new Company();
   }
}

Client
{
    private ICompany _company;

    public Client() : this (new Factory()) {}

    public Client(Factory factory)
    {
        _company = factory.CreateNewICompany();
    }

    public Client GetClientbyID(int id)
    {
       .... do stuff to get client from db
       ... got client object and companyid from db.
         client.Company = _company.GetCompanybyID(companyid);
        return client;
    }
}

 Company
 {
    private IClient _client;

    public Company() : this (new Factory()) {}

    public Company(Factory factory)
    {
        _client = factory.CreateNewIClient();
     }

    public Company GetCompanyWithAllClients(int companyid)
    {
         .... do stuff to get a company out and client ids
         .... for each client id found
          company.Clients.add(_client.GetClientByID(clientid));
          return company;
    } 
 } 
  • Неужели я все-таки ошибаюсь в DI, это заводская идея, хорошо?

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

Спасибо за любые предложения.

Ответы [ 2 ]

1 голос
/ 18 апреля 2009

Это не столько ответ, сколько прояснение проблемы. Я думаю, что ваша фабрика несколько усложняет ситуацию (в том смысле, что вы получаете исключение переполнения стека вместо невозможности компиляции)

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

public class Company : ICompany
{
    private IClient _client;

    // OK so first build a client and pass it in
    public Company(IClient client)
    {
       _client = _client;
    }
}

public class Client : IClient
{
    private ICompany _company;

    // OK so first build a company and pass it in.  Oh.  I can't... :(
    public Client(ICompany company)
    {
        _company = company;
    }    
}

У Миско есть статья об этом, которая может быть полезна: http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

В основном: дизайн вашего класса - это проблема, и она нуждается в исправлении. Фабрика просто запутывает вопрос:)

0 голосов
/ 18 апреля 2009

Может быть, вы могли бы использовать какой-нибудь инструмент ORM для своего DAL, например, NHibernate или Linq to SQL? NHibernate отобразит ваши данные в объекты с помощью двунаправленных ссылок (если хотите).

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

Ура, Rok

...