Pola Duplikasi Kelas?


11

Saat ini saya bekerja sebagai pengembang solo di proyek saya saat ini. Saya mewarisi proyek dari pengembang lain, yang sejak itu meninggalkan perusahaan. Ini adalah aplikasi web gaya model-view-controller di C #. Ini menggunakan Kerangka Entitas untuk pemetaan relasional objek. Dan ada dua set kelas yang berbeda untuk tipe dalam model domain. Satu set digunakan untuk berinteraksi dengan ORM dan yang lainnya digunakan sebagai model dalam sistem MVC. Misalnya, mungkin ada dua kelas sebagai berikut:

public class Order{
    int ID{get;set;}
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
}

dan

public class OrderModel{
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
    public OrderModel( Order from){
        this.Customer= from.Customer;
        // copy all the properties over individually
    }
    public Order ToOrder(){
        Order result =new Order();
        result.Customer = this.Customer;
        // copy all the properties over individually
    }

}

Saya dapat memikirkan beberapa kelemahan dari pendekatan ini (lebih banyak tempat untuk mengubah kode jika ada perubahan, lebih banyak objek duduk dalam memori, lebih banyak waktu dihabiskan untuk menyalin data), tetapi saya tidak begitu yakin apa kelebihannya di sini. Lebih fleksibel untuk kelas model, saya kira? Tapi saya bisa mendapatkannya dengan mensubklasifikasikan kelas entitas juga. Kecenderungan saya adalah untuk menggabungkan dua kelompok kelas ini, atau mungkin model kelas menjadi subclass dari kelas entitas. Jadi, apakah saya kehilangan sesuatu yang penting di sini? Apakah ini pola desain umum yang tidak saya ketahui? Adakah alasan bagus untuk tidak melanjutkan dengan refactor yang saya renungkan?

MEMPERBARUI

Beberapa jawaban di sini membuat saya sadar bahwa deskripsi awal saya tentang proyek itu kurang beberapa detail penting. Ada juga kelompok kelas ketiga yang ada di proyek: kelas model halaman. Merekalah yang sebenarnya digunakan sebagai model yang mendukung halaman. Mereka juga mengandung informasi yang khusus untuk UI, dan tidak akan disimpan dengan pesanan dalam database. Kelas model halaman contoh mungkin:

public class EditOrderPagelModel
{
    public OrderModel Order{get;set;}
    public DateTime EarliestDeliveryDate{get;set;}
    public DateTime LatestAllowedDeliveryDate{get;set;}
}

Saya benar-benar melihat kegunaan kelompok ketiga ini berbeda di sini, dan tidak punya rencana untuk menggabungkannya dengan sesuatu yang lain (walaupun saya mungkin akan mengganti nama).

Kelas-kelas dalam kelompok model juga saat ini digunakan oleh API aplikasi, yang saya juga akan tertarik mendengar masukan tentang apakah itu ide yang bagus.

Saya juga harus menyebutkan bahwa pelanggan yang direpresentasikan sebagai string di sini adalah untuk menyederhanakan contoh, bukan karena itu sebenarnya diwakili seperti itu dalam sistem. Sistem yang sebenarnya menjadikan pelanggan sebagai tipe berbeda dalam model domain, dengan propertinya sendiri


1
"Saya mewarisi proyek dari pengembang lain, yang sejak itu meninggalkan perusahaan" ada situs yang didedikasikan untuk cerita yang dimulai dengan cara ini .

Mengenai pembaruan Anda: itu sepertinya tipuan terlalu banyak untuk tidak cukup manfaat.
Robert Harvey

@RobertHarvey Apa yang Anda maksud sebagai terlalu banyak tipuan?
Robert Ricketts

1
Model Pesanan. OrderViewModel (apa yang Anda sebut sebagai EditOrderPageModel) adalah tipuan yang cukup; lihat jawaban saya di bawah ini.
Robert Harvey

@RobertHarvey Ini kedengarannya seperti jawaban atas pertanyaan yang sebenarnya saya coba tanyakan
Robert Ricketts

Jawaban:


16

Jadi, apakah saya kehilangan sesuatu yang penting di sini?

IYA

Meskipun ini terlihat seperti hal yang sama, dan mewakili hal yang sama dalam domain, mereka bukan objek yang sama (OOP).

Salah satunya adalah yang Orderdiketahui oleh bagian penyimpanan data dari kode. Yang lainnya adalah Orderseperti yang diketahui oleh UI. Meskipun kebetulan yang menyenangkan bahwa kelas-kelas ini memiliki sifat yang sama, mereka tidak dijamin .

Atau untuk melihatnya dari perspektif lain, pertimbangkan Prinsip Tanggung Jawab Tunggal. Motivator utama di sini adalah bahwa "kelas punya satu alasan untuk berubah". Terutama ketika berhadapan dengan kerangka kerja yang luas seperti kerangka kerja ORM dan / atau UI, objek Anda perlu diisolasi dengan baik karena perubahan pada kerangka kerja akan sering menyebabkan entitas Anda berubah.

Dengan mengikat entitas Anda ke kedua kerangka kerja, Anda membuatnya menjadi jauh lebih buruk.


7

Tujuan dari Model Tampilan adalah untuk menyediakan decoupling dalam dua cara: dengan memberikan data dalam bentuk yang diperlukan View (terlepas dari model), dan (terutama dalam MVVM) dengan mendorong beberapa atau semua logika View kembali dari View. ke Model Tampilan.

Dalam model yang dinormalkan sepenuhnya, Pelanggan tidak akan diwakili dalam Model oleh string, melainkan oleh ID. Model, jika perlu nama pelanggan, akan mencari nama dari tabel Pelanggan, menggunakan CustomerID yang ditemukan di tabel Pesanan.

Model Tampilan, di sisi lain, mungkin lebih tertarik pada Namepelanggan, bukan ID. Itu tidak perlu untuk ID kecuali Pelanggan sedang diperbarui dalam Model.

Selain itu, Model Tampilan dapat, dan biasanya memang, mengambil bentuk yang berbeda (kecuali itu adalah CRUD murni ). Objek Model Tampilan Faktur mungkin memiliki nama pelanggan, alamat, dan item baris, tetapi model tersebut berisi pelanggan dan deskripsi.

Dengan kata lain, faktur biasanya tidak disimpan dengan cara yang sama seperti yang ditampilkan.


3

Dalam beberapa hal Anda benar: Keduanya merujuk pada objek domain yang sama, yang disebut order. Tapi Anda salah sejauh ini, itu bukan duplikasi nyata dari representasi yang berbeda - berasal dari tujuan yang berbeda. Jika Anda ingin mempertahankan pesanan Anda, mis. Anda ingin mengakses setiap kolom. Tetapi Anda tidak ingin membocorkannya ke luar. Selain mendorong seluruh Entitas melalui kabel bukanlah yang Anda inginkan. Saya tahu kasus, di mana koleksi MB ordersdikirim ke klien di mana beberapa kb akan cukup.

Untuk membuat cerita panjang pendek - inilah alasan utama Anda ingin melakukan itu:

1) Enkapsulasi - Menyembunyikan informasi aplikasi Anda

2) Model Kecil cepat untuk serial dan mudah ditransmisikan

3) Mereka melayani tujuan yang berbeda, meskipun tumpang tindih, dan karena itu harus ada objek yang berbeda.

4) Kadang-kadang masuk akal untuk memiliki untuk Berbagai Pertanyaan Nilai-Objek yang berbeda . Saya tidak tahu bagaimana itu di C #, tetapi di Jawa dimungkinkan untuk menggunakan POJO untuk mengumpulkan hasil. Jika saya memerlukan satu ordersaya menggunakan Orde -Entity, tetapi jika saya hanya perlu beberapa kolom diisi dengan jumlah pada data, menggunakan Objek yang lebih kecil lebih efisien.


Cara kerangka entitas terstruktur, entitas adalah objek C # tua yang biasa, jadi mengirimnya melalui kawat tidak terlalu menjadi masalah. Saya melihat utilitas untuk dapat mengirim hanya sebagian dari isi pesanan dalam beberapa keadaan.
Robert Ricketts

Satu atau banyak bukanlah masalah seperti yang saya katakan. Tetapi ada beberapa kasus, di mana Anda memiliki MB data, yang memperlambat waktu buka Anda. Pikirkan waktu muat seluler
Thomas Junk

0

(Penafian: Saya hanya melihatnya digunakan dengan cara ini. Saya mungkin salah mengerti tujuan sebenarnya. Perlakukan jawaban ini dengan curiga.)

Berikut adalah bit lain yang hilang: konversi antara Orderdan OrderModel.

The Orderkelas terkait dengan ORM Anda, sedangkan OrderModelterkait dengan desain View Model Anda.

Biasanya, kedua metode ini akan menyediakan "dengan cara ajaib" (kadang-kadang disebut DI, IoC, MVVM, atau hal lain lagi). Artinya, alih-alih menerapkan dua metode konversi ini sebagai bagian dari OrderModel, mereka malah akan menjadi milik kelas yang didedikasikan untuk inter-konversi hal-hal ini; kelas itu entah bagaimana akan terdaftar pada framework sehingga framework dapat dengan mudah mencarinya.

public class OrderModel {
    ...
    public OrderModel(Order from) { ... }
    public Order ToOrder() { ... }
}

Alasan untuk melakukan ini adalah bahwa setiap kali ada persimpangan dari OrderModelke Orderatau sebaliknya, Anda tahu bahwa beberapa data pasti telah dimuat dari atau disimpan ke dalam ORM.


Jika saya menjaga keduanya, saya pasti ingin mengaturnya agar konversi menjadi lebih otomatis
Robert Ricketts

@RobertRicketts Hal yang saya lihat terlihat seperti ini: IMvxValueConverter . Meskipun saya mungkin salah mengerti tujuannya.
rwong
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.