Apakah ada contoh pendekatan non CRUD?


14

Saya seorang programmer tetapi juga telah bekerja sebagai seorang arsiparis. Sebagai pengarsip banyak tentang penyimpanan data.

Saya sering berdebat dengan kolega ketika datang ke operasi pada data. Saya tidak terlalu suka U dan D di CRUD. Daripada memperbarui catatan saya lebih suka menambahkan yang baru dan memiliki referensi ke catatan lama. Dengan begitu Anda membangun sejarah perubahan. Saya juga tidak suka menghapus catatan tetapi menandainya sebagai tidak aktif.

Apakah ada istilah untuk ini? Pada dasarnya hanya membuat dan membaca data? Apakah ada contoh pendekatan ini?


1
Is there a term for this? Basically only creating and reading data?Tentu ada: CR; P
yannis

7
Dari sudut pandang pengguna, itu masih CRUD. Saya tidak mengetahui adanya label khusus untuk gaya implementasi itu, tapi saya pikir itu umum di banyak aplikasi. (Stack Exchange adalah contoh yang baik ...)
Mark E. Haase

Anda mungkin ingin menonton ceramah yang disebut The Impedance Mismatch is Our Fault .
Anton Barkovsky

+1 Pada titik tertentu, seseorang akan menginginkan laporan dan sangat sulit untuk membuat laporan tentang data yang tidak ada karena "diperbarui" dari keberadaan. Saya menemukan pendekatan Anda sangat maju.
Chuck Conway

2
Anda mungkin juga ingin menonton ceramah tentang Datomic: infoq.com/presentations/The-Design-of-Datomic
Marjan Venema

Jawaban:


16

Menandai catatan yang dihapus dikenal sebagai penghapusan-lunak . Saya belum pernah mendengar frasa alternatif untuk memperbarui, tetapi saya rasa itu menyebabkan Anda menghapus dengan lembut catatan lama dan membuat yang baru.

Perlu dicatat, ini adalah teknik yang kontroversial. Lihat tautan: Con vs Pro .


11

Salah satu masalah dengan mempertahankan riwayat perubahan adalah bahwa hal itu mengacaukan database dan secara dramatis dapat meningkatkan ukurannya (tergantung pada pola penggunaan). Jadi ide yang bagus adalah menyimpan jejak audit di tempat yang terpisah, dan menyimpan tabel aplikasi yang sebenarnya hanya diisi dengan data yang relevan. Jadi setiap kali operasi CRUD dilakukan oleh aplikasi, perubahan dicatat dalam tabel audit, dan operasi CRUD dilakukan pada tabel aplikasi (tidak ada penghapusan lunak).

Dengan menjaga jejak audit terpisah memberi Anda penyimpanan data yang murni untuk aplikasi Anda untuk berinteraksi, sambil tetap mempertahankan riwayat perubahan jika Anda membutuhkannya. Sekarang Anda juga dapat mengarsipkan jejak audit secara terpisah atau bahkan menghancurkannya, tergantung pada persyaratan bisnis Anda.


3
Ini. Juga, integritas referensial menjadi mimpi buruk; Anda tidak dapat menentukan kunci asing untuk "satu catatan dalam tabel ini dengan kunci tidak unik yang tidak ditandai dihapus". Anda menyiasatinya dengan mempertahankan data untuk salinan catatan yang akan diperbarui ke tabel yang berbeda, sebelum memperbarui "copy pekerjaan" ini dengan data baru, tetapi Anda masih memiliki data besar yang harus ditangani.
KeithS

5

EventSourcing terdengar seperti pola yang mungkin Anda cari.

Mari kita ambil contoh menggunakan objek "mobil" sederhana yang ingin kita pantau warna (kode pseudo C # berikut).

public class Car {
  public string Color { get; set; }
  public Car() { this.Color = "Blue"; }
}

Dengan implementasi CRUD ketika kami memperbarui warna mobil, warna sebelumnya akan hilang.

MyCar.Color = "Red";
MyCar.Save();  // Persist the update to the database and lose the previous data

Hilangnya informasi ini menurut saya seperti yang paling ingin Anda hindari (karena itu tidak suka dengan pembaruan dan menghapus bagian dari pola CRUD).

Jika kami menulis ulang kelas mobil untuk merespons acara saat memperbarui perubahannya, itu mungkin terlihat seperti ini:

public class Car {
    public string Color { get; private set; } // Cannot be set from outside the class

    public void ApplyEvent(CarColorChangedEvent e) {
      this.Color = e.Color;
    }
}

Sekarang bagaimana kita memperbarui warna objek ini? Kita bisa membuat acara CarColorChanged !

var evnt = new CarColorChangedEvent("Red");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

Perhatikan kurangnya save pada objek model yang sebenarnya? Itu karena alih-alih mempertahankan model secara langsung, kami tetap menggunakan peristiwa yang menempatkan model ke kondisi saat ini. Peristiwa ini harus abadi .

Sekarang mari kita maju cepat dan mengubah warna beberapa kali lagi:

var evnt = new CarColorChangedEvent("Green");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

var evnt = new CarColorChangedEvent("Purple");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

Jika kita melihat penyimpanan acara kita (bisa berupa basis data hubungan, berbasis file, dll.) Kita akan melihat serangkaian acara yang berkaitan dengan objek mobil kita:

CarColorChangedEvent => Red
CarColorChangedEvent => Green
CarColorChangedEvent => Purple

Jika kami ingin membangun kembali objek mobil itu, kami dapat melakukannya hanya dengan membuat objek mobil baru dan menerapkan peristiwa dari toko acara kami ke objek tersebut.

var MyCar = new Car();
var events = MyDatabase.SelectEventsForCar("CarIdentifierHere");
foreach(var e in events) {
  MyCar.ApplyEvent(e);
}
Console.WriteLine(MyCar.Color); // Purple

Dengan aliran peristiwa, kita dapat memutar kembali keadaan mobil ke periode waktu sebelumnya hanya dengan membuat objek mobil baru dan hanya menerapkan peristiwa yang kita inginkan:

var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red

5

Acara Sourcing adalah cara untuk pergi, dan Anda harus melihat apa yang dikatakan Greg Young tentang itu.

http://goodenoughsoftware.net/

Lihat juga presentasi ini di Database-nya (Event Store). Anda juga dapat menemukan video lainnya.

http://oredev.org/2012/sessions/a-deep-look-into-the-event-store

Saya tidak akan mencari jawaban "penghapusan lunak" kecuali Anda secara khusus harus dapat mencari item yang dihapus, tetapi kemudian Anda tidak boleh menganggapnya sebagai dihapus tetapi agak diarsipkan. Saya pikir terminologi cukup penting di sini.

Saya juga tidak ingin mempertahankan "tabel versi". Semua "tabel versi" yang pernah saya lihat (termasuk pada saya mencoba untuk membersihkan saat ini - 7 tahun data rusak karena bug ... dan tidak ada cara untuk mendapatkannya kembali meskipun kami memiliki data historis .. karena itu sama korupnya) akhirnya rusak karena bug dalam kode dan pada akhirnya Anda masih kehilangan data karena Anda tidak akan pernah bisa kembali dan membuat kembali data yang rusak oleh korupsi.

Dengan model sumber acara ini bukan itu masalahnya. Anda selalu dapat memutar ulang apa yang dilakukan pengguna. Ini adalah perbedaan yang sangat penting antara CRUD dan Event Sourcing. Arsitektur Sumber Acara menyimpan acara di toko acara, dan bukan objek data atau objek model domain. Suatu peristiwa dapat dengan mudah memengaruhi banyak objek. Pikirkan solusi keranjang belanja tempat Anda mengonversi setiap item dalam keranjang belanja menjadi pesanan aktual. Satu peristiwa memengaruhi semua objek barang serta objek keranjang belanja, yang diubah menjadi objek pesanan.

Jika Anda menyimpan salinan versi setiap baris di setiap tabel dalam database, lalu bayangkan kengerian karena harus mundur ke stempel waktu tertentu, belum lagi jumlah ruang dan kinerja overhead yang gila dalam mempertahankan tabel versi itu.

Dengan Pengadaan Acara, Anda dapat dengan mudah memundurkannya, hanya dengan memutar ulang acara hingga titik waktu tertentu. Maju cepat dapat dilakukan dengan menggunakan snapshot, tetapi itu semua masalah implementasi.

Tetapi keuntungan nyata yang menurut saya akan Anda sukai, karena Anda sangat tertarik untuk tidak kehilangan data, adalah bahwa jika Anda menemukan bug dalam kode yang menyimpan data ini, maka Anda tidak perlu kembali dan membersihkan data. (yang seringkali tidak mungkin karena data hampir tidak pernah lengkap). Alih-alih hanya memperbaiki bug, dan memutar ulang semua acara. Maka Anda akan memiliki database dengan data yang benar bagus.

Dalam hal debugging, seberapa sering Anda meminta pengguna untuk memberi tahu Anda apa yang mereka lakukan ... mengapa tidak hanya memutar ulang apa yang mereka lakukan dan kemudian melangkah melalui kode! Cukup bagus ya.

Semoga ini membantu.


2

Bukan contoh Anda, tetapi dalam sistem keuangan lama Anda memiliki penyimpanan WORM . Jika Anda perlu "memperbarui" Anda menulis catatan baru dan Anda selalu menyebut catatan terakhir sebagai saat ini tetapi tidak ada data yang berkomitmen dapat ditimpa.

Banyak orang membawa ide itu ke sistem yang lebih baru. Saya telah mendengar apa yang Anda gambarkan disebut sebagai tabel WORM, tetapi hanya di lingkaran itu.


2

Ya itu cukup umum dalam sistem perusahaan pada dasarnya ada dua pendekatan: -

  • "bi - temporal" di mana setiap catatan memiliki valid dari dan berlaku untuk cap waktu (catatan "saat ini" memiliki valid hingga tanggal "selamanya" - null, "9999-12-31" atau nilai tinggi semacam itu). Catatan tidak pernah dihapus sebagai gantinya tanggal "valid ke" diatur ke waktu saat ini dan dalam hal pembaruan, catatan baru dimasukkan dengan valid dari waktu saat ini dan selamanya berlaku untuk tanggal.
  • "tabel sejarah" - setiap kali catatan diubah, salinan catatan lama dibuang di tabel riwayat / log dengan stempel waktu untuk acara tersebut.

Ada banyak variasi granularitas untuk kedua pendekatan. mis. Jika jumlah widget pada item pesanan diubah, apakah Anda mempertahankan histori untuk seluruh pesanan atau hanya satu item itu?

Secara umum "bi-temporal" adalah banyak pekerjaan tambahan dan hanya layak jika Anda memiliki banyak kasus penggunaan seperti "auditor mendapat status pesanan per 31 Desember".



-2

pada dasarnya mentah tidak dapat diselesaikan tanpa 4 hal ini. Crud berarti Buat, Baca, Perbarui, dan hapus sehingga saat Anda hanya mencoba membaca data, Anda dapat menggunakan kueri sederhana untuk itu, tetapi ketiga hal ini dilampirkan pada satu dan konsep database lainnya yang sederhana

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.