Rozdzielenie pobierania danych i obiektów biznesowych między warstwami DAL i BLL

9

Przed opublikowaniem tego pytania przeprowadziłem kilka badań. Wśród innych pytań lub postów jedno z nich znajduje się poniżej. Nie mogłem zrozumieć, jak to ustalić ...

Obiekty biznesowe w warstwie dostępu do danych

Mam repozytorium, a warstwy biznesowe wywołują repozytorium w celu pobrania danych. Powiedzmy, że mam następujące klasy dla BLL i DAL:

class BllCustomer
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public BllAddress Address {get; set;}
}

class BllAddress
{
     public int AddressId {get; set;}
     public String Street {get; set;}
     public String City {get; set;}
     public String ZipCode {get; set; }
}

class DalCustomer 
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public int AddressID {get; set;}
}

class DalAddress
{
     public int AddressId {get; set;}
     public String Street {get; set;}
     public String City {get; set;}
     public String ZipCode {get; set; }
}

Jeśli BLL chce pobrać obiekt Customer, wywołałby GetCustomerById (customerId) w DAL.

Oto moje obawy, których nie mogłem zrozumieć:

  1. Nie widzę, jak ustalić, jaki obiekt powinien zwrócić GetCustomerById w DAL? Czy powinien zwrócić BllCustomer czy DalCustomer?

  2. Gdzie powinno być pobierane (i / lub konwertowane na obiekt biznesowy) adresy powiązane z klientem?

Jeśli DAL zwróci obiekty Dal, wówczas logika pobierania i wypełniania adresu może znajdować się tylko w BLL. Jeśli DAL zwraca obiekty BLL, wówczas logika do pobrania i wypełnienia adresu może znajdować się w BLL lub DAL. Obecnie DAL zwraca obiekty biznesowe, a logika do ich wypełnienia znajduje się w DAL.

Z tego, co czytam, wydaje mi się, że nie ma dobra ani zła. Z linku zamieszczonego powyżej są ludzie, którzy mówią w jedną stronę, a inni mówią w drugą stronę. Ale jak ustalić, który z nich najlepiej pasuje do mojej sprawy?

Każda pomoc będzie mile widziana.

ShamirDaj
źródło
2
Moje pierwsze pytanie brzmi: czy jest to starsza aplikacja? Istnieje wiele ram ORM, które powodują, że ten rodzaj kodu jest przestarzały, i zachęcam do rozważenia takiego szkieletu ...
JDT
@JDT Nie jestem pewien, co masz na myśli, używam Entity Framework i mam dokładnie ten sam problem. Jak rozumiem, nie powinieneś używać ORM jako obiektów domeny, więc gdzie odbywa się tłumaczenie?
pseudokoder
Dlaczego struktura ORM nie zwraca również obiektów, które są również obiektami domeny?
JDT
3
@JDT ORM (w tym przypadku EF) zwraca klasy jednostek, które reprezentują zwykle jedną tabelę bazy danych na klasę. Jest to zwykle podobne do klas domen, ale niekoniecznie takie same. Może po prostu mówisz, że można używać klas ORM jako klas domenowych? Czytałem w wielu miejscach, że jest to nie-nie.
pseudokoder

Odpowiedzi:

5

Nie widzę, jak ustalić, jaki obiekt powinien zwrócić GetCustomerById w DAL? Czy powinien zwrócić BllCustomer czy DalCustomer?

Powinien zwrócić obiekt DalCustomer , zwrócenie obiektu BllCustomer złamie zasadę pojedynczej odpowiedzialności . Obiekt DalCustomer można wyświetlić jako interfejs lub umowę używane przez warstwę biznesową (lub konsumenta). W efekcie, jeśli zwróci klienta BllCustomer, DAL musiałby obsłużyć każdy obiekt warstwy biznesowej, który go wywołuje lub mógłby go wywołać.

Gdzie powinno być pobierane (i / lub konwertowane na obiekt biznesowy) adresy powiązane z klientem?

Konwersji należy dokonać w modelu widoku lub menedżerze. Musisz mieć pośrednika, aby zadzwonić do usługi lub komponentu dostępu do danych. Jeśli czujesz potrzebę, możesz dokonać konwersji w swoim obiekcie BllCustomer . Ale kiedy zamieniasz DAL z MSSQL na Oracle, na przykład zwracany obiekt (lub interfejs) musi pozostać taki sam.

Najlepiej, aby warstwa biznesowa była również niezależna od warstwy danych. Warstwa biznesowa odpowiada za reguły biznesowe. To tutaj dodasz swoje sprawdzania poprawności za pomocą ram sprawdzania poprawności w celu egzekwowania reguł biznesowych.

Derika
źródło
4

Twoje repozytorium powinno zwrócić BLL lub obiekt domeny. istnieje prawdopodobieństwo, że w ogóle nie potrzebujesz obiektu DAL.

public class Customer
{
    public string Name {get; private set;}
    public Customer(string name)
    {
        this.Name = name;
    }
}

public class Repository
{
    public Customer GetCustomer(string id)
    {
        //get data from db
        return new Customer(datarow["name"]);
    }
}
Ewan
źródło
Czy BLL lub osobna biblioteka klas powinna pokazywać interfejsy zamiast konkretnych klas takich jak Customer?
Yola
1
Nie. Ujawnianie konkretnych klas jest w porządku. Przydałby się interfejs repozytorium
Ewan
3

Zazwyczaj DAL nie ma wiedzy na temat BLL. Pomyśl o tym w ten sposób, inna aplikacja z innym BLL mogłaby używać tego samego DAL. Aplikacja / moduł zobowiązań i aplikacja należności dla tej samej firmy dzieliłyby dane (klienci, opłaty, płatności itp.). Próba posiadania jednej biblioteki DLL posiadającej znajomość więcej niż jednej BLL byłaby bardzo trudna i niepotrzebna. Pozwoliłoby to również na zmianę przechowywania danych bez wpływu na BLL (o ile nie zepsujesz interfejsów).

Możesz teraz przekazać obiekt DAL do BLL lub możesz utworzyć trzeci zestaw obiektów: Entity. Zawierają one tylko wartości, które należy przekazać razem. DAL będzie odwoływał się do encji i wchodził w interakcje z twoją pamięcią / bazą danych, a BLL obsługiwałby całą logikę i odnosiłby się do DAL.

class EntCustomer
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public BllAddress Address {get; set;}
}
class BllCustomer
{
   //reference EntCustomer, DalCustomer and handle business rules/logic
}

class DalCustomer 
{
   //reference EntCustomer and interact with data storage
}
JeffO
źródło
Dziękuję za Twój komentarz. Zgadzam się z tobą. Widzę już, że nasz DAL / (repozytorium) jest już wypełniony logiką, np. Jeśli typ to A, a następnie przejdź do pobierania danych z tabeli B, ale jeśli typ to C, to przejdź do pobierania danych z tabeli C. Ale jestem mylony z twoim przykładem używania EntCustomer. W moim przypadku DalCustomer jest odzwierciedleniem tabel w DB. Czy możesz podać więcej przykładów, w jaki sposób używany jest EntCustomer lub dlaczego powinienem go użyć i jakie są korzyści. Zastanawiam się nad zmianą DAL, aby zwrócić DalObjects do BLL. Bll zawiesi konwersję do Business Objs, pobierze i wypełni zagnieżdżone obiekty obj.
ShamirDaj
Czy możesz podać więcej opinii?
ShamirDaj
Myślę, że celem obiektów Ent jest po prostu przesyłanie danych między DAL i BLL. Twoje klasy DAL mogą nadal odzwierciedlać strukturę db, ale te klasy byłyby wewnętrzne dla DAL. Gdy BLL prosi o dane z DAL, DAL pobierze wymagane obiekty DAL z bazy danych (dalcustomer + daladdress) i zbuduje z nich instancję EntCustomer i zwróci ją do BLL.
artokai
-1

DAL powinien być niezależny od BL i BL zależny od DAL. Twój interfejs powinien mieć dostęp do danych tylko przez BL. Dobrą praktyką jest zwracanie DataTable lub DataRow z DAL, a następnie Konwertowanie DataTable / DataRow na obiekty BL. Kiedy twój interfejs użytkownika potrzebuje dostępu do danych, może uzyskać dostęp z BL. Interfejs użytkownika będzie więc niezależny od nazwy kolumny i typu bazy danych (SQL Server, Oracle ..). W ten sposób Twój interfejs użytkownika będzie całkowicie niezależny od DAL. Osobiście wolę nazwę klasy jak „CustomerBL”, nie używaj słowa BL na początku nazwy klasy.

Poniżej patrz przykładowy kod.

//Customer Class
class BllCustomer
{
    public int CustomerId { get; set; }
    public String Name { get; set; }
    public BllAddress Address { get; set; }

    public static BllCustomer GetByCustomerId(int id)
    {
        DataRow dr = DalCustomer.GetByCustomerId(id);
        if (dr == null)
            return null;
        BllCustomer oCust = new BllCustomer();
        oCust.CustomerId = int.Parse(dr["CustomerId"].ToString());
        //Do for other class members and load values

        return oCust;
    }
}


class DalCustomer
{

    public static DataRow GetByCustomerId(int id)
    {
        //Get Data row from Database and return Datarow
        DataRow CustomerRow = GETFROMDATABASE("SELECT * from CUSTOMER");
        return CustomerRow;
    }
}
Jigneshk
źródło
Err ... Czy to nie znaczy, że twoja BLL musi mieć wiedzę na temat formatu / struktury twoich tabel danych? ...
Paul