3-х уровневая проблема архитектуры - PullRequest
2 голосов
/ 26 февраля 2011

Я пытаюсь создать простое приложение для 3-уровневой архитектуры с ASP.NET и C #.Я подошел к проблеме с круговой зависимостью.У меня есть Студенческий класс на бизнес-уровне.У меня есть интерфейс для уровня представления с этими методами:

void SaveStudent(Student student);
Student[] GetStudents();

Это выглядит нормально.

Но у меня также есть интерфейс из уровня доступа к данным для бизнеса с этими методами:

void InsertStudent(Student student);
Student[] ReadAllStudents();

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

Как мне тогда передать данные?

Если я помещу класс Student в DAL, то мой уровень презентации будет вынужден зависеть от доступа к даннымплохой слой.

Я никогда не пытался создать 3-уровневую архитектуру раньше.

Как решить эту проблему?Будьте свободны, чтобы изменить мои методы интерфейса, если это необходимо.

Ответы [ 6 ]

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

Эту проблему обычно решают, помещая ваш класс Student в отдельную сборку Models (назовите ее как хотите), которая будет доступна всем слоям. В крупномасштабных n-уровневых архитектурах эти классы обычно содержат не что иное, как данные, и их обычно называют объектами преобразования данных (DTO). Любая бизнес-логика, которая воздействует на эти объекты, будет храниться на бизнес-уровне (BL), который обычно предоставляется как услуга (т. Е. WCF). Сервис - это просто посредник, вы можете создавать его таким образом, даже когда весь код находится на одной машине и даже в одном и том же процессе. Как минимум, вы хотите разделить свои проблемы (пользовательский интерфейс, бизнес-уровень, DTO, DAL) на уровне сборки.

В вашем случае метод GetStudents будет представлен в сервисе Business Layer и вернет DTO для студентов. Бизнес-уровень будет содержать ссылку на уровень доступа к данным (DAL), на котором он будет вызывать InsertStudent. Опять же, как я уже говорил, DAL и BL имеют ссылку на сборку Models, но самое главное, DAL не зависит от BL.

Клиент -> Сервис бизнес-уровня -> Уровень доступа к данным

<------------------ Студент (DTO) ------------------>

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

Ключевым понятием в архитектуре n-tier является то, что уровень n-th знает только уровень n+1-th. Таким образом, ваш пользовательский интерфейс будет вызывать бизнес-логику, а бизнес-логика - уровень доступа к данным.

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

Вам необходимо ввести еще один слой под названием Модель. Этот слой будет определять класс Student только как объект данных. (Нет методов Сохранить или Получить в этом слое).

Слой модели может быть в своем собственном проекте (и, следовательно, в своей собственной dll). Теперь назовите dll во всех слоях (Presentation, Business и DA). Используйте тип Student для хранения только элементов данных.

На бизнес-уровне создайте ссылку на уровень DA и создайте класс Student с методом SaveStudent. На уровне DA ссылайтесь только на слой Model и реализуйте метод save student. (Обратите внимание, что это показывает только уровень и классы, которые должны иметь эти уровни, в идеале классы должны реализовывать интерфейсы, предназначенные для этой цели, но это само по себе не является частью вашего вопроса)

namespace Model{
class Student
{
    public string Name { get; set; }
    public String Address { get; set; }
    // more student properties here ..
    // No methods like SaveStudent in this class , thats up into the business layer
    public bool IsValid(){ // validate the student here }
}

}

namespace Business{
class Student
{
    // call this method from your Presentation layer
    public void SaveStudent(Model.Student student)
    {
        if (student.IsValid())
        {
            DataAccess.StudentDAO student = new DataAccess.StudentDAO();
            student.SaveStudent(student);
        }
        else
        {
            throw new ApplicationException("Invalid student");
        }

    }
}

}

namespace DataAccess{    
class StudentDAO
{
    public void SaveStudent(Model.Student student)
    {
        // impl here to save a student informatin to a 
        // persistent storage
    }

}

}

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

Вы должны поместить службу между уровнями представления и постоянства.Уровень персистентности вызывает сервис, который взаимодействует с вашей моделью и уровнями персистентности для выполнения запроса.

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

  1. Он сохраняет презентацию отдельно от всего остального, поэтому вы можете изменять или добавлять новые презентации по своему желанию.
  2. Он инкапсулирует бизнес-логику в повторно используемый компонент вместо блокировкиэто в презентации.
  3. Это делает безопасность, ведение журналов и т. д. более понятной, потому что вы можете украсить вызовы служб сквозными задачами, используя аспектно-ориентированное программирование.

Вот какинтерфейсы могут выглядеть в Java - переведите на язык по вашему выбору:

package model;

public class Foo
{
    private Long id;
    private String name;
}

package service;

public interface FooService
{
    Foo findFoo(Long id);
    List<Foo> findAllFoos();
    void saveAllFoos(List<Foo> foos);
    void delete(Foo foo);
}

package persistence

public interface GenericDao<K, V>
{
    List<V> find();
    V find(Long id);
    K save(V value);
    List<K> save(List<V> values);
    void update(V value);
    void delete(V value);
}

So presentation->service->persistence;Служба использует пакеты модели и персистентности для выполнения запросов, которые должны соответствовать сценариям использования.

Ваша презентация вообще не должна знать об объектах модели.Отправьте что-нибудь вроде XML, JSON или другого сериализованного формата, и презентация просто отобразит его.

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

Не следует звонить из DAL в BLL (уровень бизнес-логики), просто наоборот.

// Will contain details about your UI - taking data from text fields, etc
// and passing it to the business object
class Student_UI    
{
  Student_BL _blObject = new Student_BL();

  void SaveStudent()  
  {  
    Student student = new Student();
    // Get student details from UI...
    _blObject.SaveStudent(student);  
  }  

  DisplayStudents()  
  {  
    Student[] students = _blObject.GetStudents();  
    // display students...
  }  
}

class Student_BL
{
  Student_DAL _dalObject = new Student_DAL();

  void SaveStudent(Student student)  
  {  
    _dalObject.InsertStudent(student);  
  }  

  Student[] GetStudents()  
  {  
    return _dalObject.ReadAllStudents();  
  }  
}
0 голосов
/ 26 февраля 2011

Приведенный ниже код иллюстрирует разделение проблем на уровне сервиса (или бизнес-логики), предоставляя метод для внедрения в репозиторий.

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

Если вы используете подход IoC (такой как StructureMap или Unity), вы можете использовать контейнер для выполнения инъекции.

public class StudentService
{
  private IStudentRepository _studentRepository;

  public StudentService(IStudentRepository studentRepository)
  {
    _studentRepository = studentRepository;
  }
}

public interface IStudentRepository
{
  void Save(Student student);
  Student[] GetStudents();
}

public class StudentRepository : IStudentRepository
{
 ... implement the methods defined in the interface ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...