Melepaskan tingkah laku objek di luar akses data
MelayuTL;DR: Mengalih keluar atau menggantikan getter dengan kaedah yang kaya tingkah laku yang melaksanakan operasi alih-alih mendedahkan keadaan dalaman.
Melayu
TL;DR: Mengalih keluar atau menggantikan getter dengan kaedah yang kaya tingkah laku yang melaksanakan operasi alih-alih mendedahkan keadaan dalaman.
Masalah yang diselesaikan
- Melayu
- Objek anemik Melayu
- Penyambung yang berlebihan Melayu
- Kehilangan encapsulation Melayu
- Mutasi Essence Melayu
- Undang-undang Demeter Pelanggaran Melayu
- Pengumpulan maklumat Melayu
- Eksposur dalaman Melayu
- Obsession yang primitif Melayu
Tag: kode yang berbau
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxix
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxv
Langkah
- Melayu
- Menentukan getter yang mendedahkan keadaan objek dalaman Melayu
- Temukan semua kegunaan pisau dalam codebase Melayu
- Perilaku bergerak yang menggunakan getter ke dalam objek itu sendiri Melayu
- Mencipta kaedah yang mendedahkan niat yang melaksanakan operasi (menghapuskan prefiks get) Melayu
- Memperbarui kod anda untuk menggunakan kaedah baru Melayu
Kod sampel
sebelum
public class Invoice {
private List<LineItem> items;
private Customer customer;
private LocalDate dueDate;
public Invoice(Customer customer, LocalDate dueDate) {
this.customer = customer;
this.dueDate = dueDate;
this.items = new ArrayList<>();
}
public void addItem(LineItem item) {
// This is the right way
// to manipulate the internal consistency
// adding assertions and access control if necessary
items.add(item);
}
public List<LineItem> getItems() {
// You are exposing your internal implementation
// In some languages, you also open a backdoor to
// manipulate your own collection unless you return
// a copy
return items;
}
public Customer getCustomer() {
// You expose your accidental implementation
return customer;
}
public LocalDate getDueDate() {
// You expose your accidental implementation
return dueDate;
}
}
Invoice invoice = new Invoice(customer, dueDate);
// Calculate the total violating encapsulation principle
double total = 0;
for (LineItem item : invoice.getItems()) {
total += item.getPrice() * item.getQuantity();
}
// Check if the invoice is overdue
boolean isOverdue = LocalDate.now().isAfter(invoice.getDueDate());
// Print the customer information
System.out.println("Customer: " + invoice.getCustomer().getName());
Selepas
public class Invoice {
private List<LineItem> items;
private Customer customer;
private LocalDate dueDate;
public Invoice(Customer customer, LocalDate dueDate) {
this.customer = customer;
this.dueDate = dueDate;
this.items = new ArrayList<>();
}
public void addItem(LineItem item) {
items.add(item);
}
// Step 3: Move behavior that uses the getter into the object
public double calculateTotal() {
// Step 4: Create intention-revealing methods
double total = 0;
for (LineItem item : items) {
total += item.price() * item.quantity();
}
return total;
}
public boolean isOverdue(date) {
// Step 4: Create intention-revealing methods
// Notice you inject the time control source
// Removing the getter and breaking the coupling
return date.isAfter(dueDate);
}
public String customerInformation() {
// Step 4: Create intention-revealing methods
// You no longer print with side effects
// And coupling to a global console
return "Customer: " + customer.name();
}
// For collections, return an unmodifiable view if needed
// Only expose internal collaborators if the name
// is an actual behavior
public List<LineItem> items() {
return Collections.unmodifiableList(items);
}
// Only if required by frameworks
// or telling the customer is an actual responsibility
// The caller should not assume the Invoice is actually
// holding it
public String customerName() {
return customer.name();
}
// You might not need to return the dueDate
// Challenge yourself if you essentially need to expose it
// public LocalDate dueDate() {
// return dueDate;
// }
}
// Client code (Step 5: Update client code)
Invoice invoice = new Invoice(customer, dueDate);
double total = invoice.calculateTotal();
boolean isOverdue = invoice.isOverdue(date);
System.out.println(invoice.customerInformation());
Jenis
- Melayu
- [x] Semi automatik Melayu
Keselamatan ️
Ini refactoring biasanya selamat tetapi memerlukan pelaksanaan berhati-hati.
Anda perlu memastikan semua penggunaan getter diidentifikasi dan digantikan dengan kaedah tingkah laku baru.
Risiko terbesar berlaku apabila getter mengembalikan objek atau koleksi yang boleh berubah, kerana kod klien mungkin telah mengubah objek ini.
Anda perlu mengesahkan bahawa tingkah laku tidak berubah melalui ujian yang komprehensif sebelum dan selepas refactoring.
Untuk koleksi, kembalikan salinan atau pandangan yang tidak boleh diubahsuai untuk mengekalkan keselamatan semasa peralihan.Pada kerangka kerja yang memerlukan capaian harta, anda mungkin perlu menyimpan aksesori mudah tanpa prefiks "capaian" di samping kaedah yang kaya tingkah laku anda.
Seperti biasa, anda perlu menambah cakupan tingkah laku (bukan struktural) kepada kod anda sebelum anda melakukan refactoring.
Mengapa kod ini lebih baik?
Kod refactored lebih baik kerana ia mematuhiBeritahu-Jangan TanyaPrinsip ini, menjadikan objek anda pintar daripada hanya pemegang data anemik.
Penyelesaian ini menyentralisasikan logik yang berkaitan dengan data objek dalam objek itu sendiri, mengurangkan duplikasi. ia menyembunyikan butiran pelaksanaan, membolehkan anda mengubah persembahan dalaman tanpa menjejaskan kod klien
Pendekatan ini mengurangkanSambungankerana klien tidak perlu tahu tentang struktur dalaman objek.
Ia juga mencegah pelanggaran kepada Undang-undang Demeter dengan menghapuskan rantai getter.
Sejak yangEssence tidak diubahsuai, penyelesaian membolehkan pengesahan yang lebih baik dan penguatkuasaan peraturan perniagaan dalam objek.
Bagaimanakah ia boleh meningkatkan kesuburan? ️
Menghapuskan getter meningkatkanBijectionantara kod dan realiti dengan membuat objek bertindak lebih seperti rakan-rakan dunia sebenar mereka.
Dalam dunia sebenar, objek tidak mendedahkan keadaan dalaman mereka kepada orang lain untuk dimanipulasi - mereka melakukan operasi berdasarkan permintaan.
Sebagai contoh, anda tidak meminta akaun bank untuk baki dan kemudian mengira sama ada pengeluaran adalah mungkin.Sebaliknya, anda bertanya kepada akaun, "Bolehkah saya menarik $ 100?"
Anda mencipta persembahan yang lebih setia konsep domain dengan memodelkan objek anda untuk melaksanakan operasi daripada mengekspos data.
Ini mengukuhkan korespondensi satu kepada satu antara dunia sebenar dan model pengiraan anda, menjadikan kod anda lebih intuitif dan selaras dengan cara orang berfikir mengenai domain masalah.
Pendekatan ini mengikutPetaprinsip dengan memastikan bahawa objek pengiraan mencerminkan entiti dunia sebenar dalam struktur dan tingkah laku.
Perbezaan ☀️
Kerangka kerja dan perpustakaan sering mengharapkan kaedah getter untuk serialisasi / deserialisasi.
Asas kod warisan mungkin mempunyai penggunaan getter yang meluas yang sukar untuk refactor semua pada satu masa.
Ujian unit boleh menjadi lebih mencabar kerana keadaan dalaman kurang boleh diakses. Ingat, anda tidak boleh menguji kaedah peribadi.
Reaktor dengan AI
MelayuPrompt disyorkan: 1. mengenal pasti getter yang mendedahkan keadaan objek dalaman 2. mencari semua penggunaan getter dalam pangkalan kod 3. memindahkan tingkah laku yang menggunakan getter ke dalam objek itu sendiri 4. mencipta kaedah yang mendedahkan niat yang melaksanakan operasi (memadamkan prefiks get) 5. mengemas kini kod anda untuk menggunakan kaedah baru
Melayu
Prompt disyorkan: 1. mengenal pasti getter yang mendedahkan keadaan objek dalaman 2. mencari semua penggunaan getter dalam pangkalan kod 3. memindahkan tingkah laku yang menggunakan getter ke dalam objek itu sendiri 4. mencipta kaedah yang mendedahkan niat yang melaksanakan operasi (memadamkan prefiks get) 5. mengemas kini kod anda untuk menggunakan kaedah baru
MelayuTiada arahan yang betul dengan arahan khusus ChatGPT ChatGPT Claude Claude Perplexity Perplexity Copilot Copilot Gemini Gemini DeepSeek DeepSeek Meta AI Meta AI Grok Grok Qwen QwenTiada arahan yang betul
Dengan arahan khususDengan arahan khusus
MelayuChatGPTMelayuChatGPTMelayuChatGPTChatGPT
ChatGPTChatGPT
oleh ClaudeKlodKlod
KlodPerplexiti Perplexiti Perplexitiperpecahanperpecahan
perpecahanperpecahan
Penerbangan CopilotMelayuPilot kanak-kanak
Pilot kanak-kanak
Pilot kanak-kanakPilot kanak-kanak
Remaja GeminiMelayuGemini
MelayuGemini
Gemini
Perkhidmatan DeepSeekDeepSeekDeepSeek
DeepSeekDeepSeek
Target ialah AITarget yangMelayuTarget yang
MelayuGrokMelayuGrokMelayuGrokGrok
GrokGrok
Melayu qwenMelayuMelayu️ ️
- Melayu
- Encapsulasi Melayu
Tahap
- Melayu
- [x] Menengah Melayu
Penyesuaian yang berkaitan
Saya tahu
Kredit
imej olehKrisialahdaripada Pixabay
Artikel ini merupakan sebahagian daripada siri Refactoring.