The Coupler

The Coupler adalah kelompok code smell yang menyebabkan keterikatan berlebihan antara kelas-kelas atau menunjukkan apa yang terjadi jika keterikatan digantikan oleh delegasi berlebihan.

Feature Envy

Feature Envy adalah sebuah code smell yang di mana sebuah kelas atau modul menggunakan metode atau data dari kelas lain secara berlebihan, menunjukkan bahwa kelas yang bergantung mungkin mencoba melakukan terlalu banyak hal atau bahwa desainnya mungkin kurang terstruktur. Dengan kata lain, jika sebuah kelas atau modul menggunakan data atau metode dari kelas lain lebih dari miliknya sendiri, itu mungkin merupakan tanda bahwa kelas yang bergantung "cemburu" terhadap fitur dari kelas lain tersebut. Hal ini dapat menyebabkan keterikatan yang erat antara kelas-kelas tersebut, yang dapat membuat kode menjadi sulit untuk dipelihara dan dipahami.

Perawatan

Jika ada perubahan pada data dan fungsi yang terkait pada saat yang sama, biasanya disarankan untuk menyimpannya di tempat yang sama. Data dan fungsi yang berkaitan cenderung diubah bersamaan (meskipun ada pengecualian).

Keuntungan

Kapan Untuk Diabaibaikan

Kadang-kadang perilaku sengaja dipisahkan dari kelas yang menyimpan data. Keuntungan biasanya dari ini adalah kemampuan untuk secara dinamis mengubah perilaku

Contoh

Masalah

                                
                                    
public class Phone {
    private final String unformattedNumber;

    public Phone(String unformattedNumber) {
        this.unformattedNumber = unformattedNumber;
    } 

    public String getAreaCode() {
        return unformattedNumber.substring(0,3);
    } 

    public String getPrefix() {
        return unformattedNumber.substring(3,6);
    } 

    public String getNumber() {
        return unformattedNumber.substring(6,10);
    } 
}

public class Customer {
    private Phone mobilePhone;

    public String getMobilePhoneNumber() {
        return "(" +
            mobilePhone.getAreaCode() + ") " +
            mobilePhone.getPrefix() + "-" +
            mobilePhone.getNumber();
    } 
}  
                                            
                                
                            

Solusi

                                
                                    
 public class Phone {
    private final String unformattedNumber;	
    
    public Phone(String unformattedNumber) {
        this.unformattedNumber = unformattedNumber;
    } 
    
    public String getAreaCode() {
        return unformattedNumber.substring(0,3);
    } 

    public String getPrefix() {
        return unformattedNumber.substring(3,6);
    } 

    public String getNumber() {
        return unformattedNumber.substring(6,10);
    } 
        
    public String getFormattedNumber() {
        return "(" + getAreaCode() + ") " + getPrefix() + "-" + getNumber(); 
    }
}  

public class Customer {
    private Phone mobilePhone;	
    
    public String getMobilePhoneNumber() {
        return mobilePhone.getFormattedNumber();
    }
}                
                                                      
                                
                            

Dalam contoh ini, kelas Customer menggunakan metode kelas Phone secara berlebihan, yang merupakan tanda "Feature Envy". Ini dapat menyebabkan tingkat keterikatan yang tinggi antara kedua kelas tersebut dan duplikasi kode yang tidak perlu.

Untuk mengatasi masalah kode ini, salah satu solusinya adalah memindahkan metode getMobilePhoneNumber ke kelas Phone dan memodifikasinya agar mengembalikan nomor telepon yang diformat secara langsung. Kita memindahkan metode getFormattedNumber dari kelas Customer ke kelas Phone. Dengan cara ini, kelas Phone bertanggung jawab untuk memformat nomor teleponnya sendiri, yang mengatasi masalah "Feature Envy" dalam kode. Kelas Customer sekarang hanya memanggil metode getFormattedNumber pada objek Phone untuk mendapatkan nomor telepon yang diformat.

Inappropiate Intimancy

Inappropriate intimacy adalah code smell yang terjadi ketika kelas atau modul terlalu erat terkait, menyebabkan interaksi atau ketergantungan yang berlebihan. Hal ini dapat mengakibatkan fleksibilitas yang berkurang, tantangan pemeliharaan yang meningkat, dan kesulitan dalam pengujian dan pemahaman kode.

Perawatan

Keuntungan

Contoh

Masalah

                                
                                    
public class Phone {
    private final String unformattedNumber;

    public Phone(String unformattedNumber) {
        this.unformattedNumber = unformattedNumber;
    } 

    public String getAreaCode() {
        return unformattedNumber.substring(0,3);
    } 

    public String getPrefix() {
        return unformattedNumber.substring(3,6);
    } 

    public String getNumber() {
        return unformattedNumber.substring(6,10);
    } 
}

public class Customer {
    private Phone mobilePhone;

    public String getMobilePhoneNumber() {
        return "(" +
            mobilePhone.getAreaCode() + ") " +
            mobilePhone.getPrefix() + "-" +
            mobilePhone.getNumber();
    } 
}  
                                            
                                
                            

Solusi

                                
                                    
 public class Phone {
    private final String unformattedNumber;	
    
    public Phone(String unformattedNumber) {
        this.unformattedNumber = unformattedNumber;
    } 
    
    public String getAreaCode() {
        return unformattedNumber.substring(0,3);
    } 

    public String getPrefix() {
        return unformattedNumber.substring(3,6);
    } 

    public String getNumber() {
        return unformattedNumber.substring(6,10);
    } 
        
    public String getFormattedNumber() {
        return "(" + getAreaCode() + ") " + getPrefix() + "-" + getNumber(); 
    }
}  

public class Customer {
    private Phone mobilePhone;	
    
    public String getMobilePhoneNumber() {
        return mobilePhone.getFormattedNumber();
    }
}                
                                                      
                                
                            

Dalam contoh ini, kelas Customer menggunakan metode kelas Phone secara berlebihan, yang merupakan tanda "Feature Envy". Ini dapat menyebabkan tingkat keterikatan yang tinggi antara kedua kelas tersebut dan duplikasi kode yang tidak perlu.

Untuk mengatasi masalah kode ini, salah satu solusinya adalah memindahkan metode getMobilePhoneNumber ke kelas Phone dan memodifikasinya agar mengembalikan nomor telepon yang diformat secara langsung. Kita memindahkan metode getFormattedNumber dari kelas Customer ke kelas Phone. Dengan cara ini, kelas Phone bertanggung jawab untuk memformat nomor teleponnya sendiri, yang mengatasi masalah "Feature Envy" dalam kode. Kelas Customer sekarang hanya memanggil metode getFormattedNumber pada objek Phone untuk mendapatkan nomor telepon yang diformat.

Message Chain

Message Chain terjadi ketika sebuah klien meminta objek lain, objek tersebut meminta objek lain lagi, dan begitu seterusnya. Rantai-rantai ini berarti bahwa klien tergantung pada navigasi sepanjang struktur kelas. Perubahan apa pun dalam hubungan-hubungan ini memerlukan modifikasi pada klien.

Perawatan

Keuntungan

Kapan Untuk Diabaibaikan

Pengelolaan delegasi yang terlalu agresif dapat menyebabkan kode di mana sulit untuk melihat di mana fungsionalitas sebenarnya terjadi. Ini merupakan cara lain untuk mengatakan, hindari smell Middle Man juga.

Contoh

Masalah

                                
                                    
public class Order {  
    private Customer customer;  

    public Order (Customer customer) {
        this.customer = customer;
    }

    public String getCustomerAddress() {
        return customer.getAddress().getStreet() + ", " 
        + customer.getAddress().getCity() + ", " + 
        customer.getAddress().getCountry()();
    }
}  

public class Customer { 
    private Address address;	 

    public Customer (Address address) { 
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }
}  

public class Address {
    private String street; 
    private String city; 
    private String country; 

    public Address (String street, String city, String country) {
        this.street = street;
        this.city = city; 
        this.country = country; 
    }

    public String getStreet() {
        return street;
    }
    

    public String getCity() {
        return city; 
    }

    public String getCountry() {
        return country; 
    }
}  
                                            
                                
                            

Solusi

                                
                                    
public class Address {
    private String street; 
    private String city; 
    private String country; 
 
    public Address (String street, String city, String country) {
        this.street = street;
        this.city = city; 
        this.country = country; 
    }
 
    public String getFullAddress() {
        return street + ", " + city + ", " + country; 
    }
}
                                                      
                                
                            

Dalam contoh ini, Kelas Order perlu mendapatkan alamat pelanggan, sehingga ia memanggil metode getAddress() pada objek Customer, yang mengembalikan objek Address. Kemudian, kelas Order memanggil metode getStreet(), getCity(), dan getCountry() pada objek Address untuk mendapatkan bagian-bagian individu dari alamat tersebut. Ini adalah contoh dari rantai pesan, karena kelas Order melakukan beberapa pemanggilan metode pada objek lain untuk mendapatkan informasi yang dibutuhkannya.

Untuk mengatasi masalah kode ini, kita bisa menambahkan sebuah metode ke kelas Address yang mengembalikan alamat lengkap sebagai string tunggal. Kemudian, Anda dapat memodifikasi kelas Order untuk memanggil metode baru ini daripada melakukan beberapa pemanggilan metode pada objek Address. Hal ini menghilangkan rantai pesan dan membuat kode lebih mudah dibaca dan dipelihara.

Middle Man

Middle Man terjadi ketika sebuah kelas hanya melakukan satu tindakan, mendelegasikan tindakan tersebut ke kelas lain. Hal ini dapat membuat kode menjadi lebih sulit dibaca dan dipelihara, karena menambahkan tingkat indireksi yang tidak perlu.

Perawatan

Jika sebagian besar dari kelas-kelas sebuah metode mendelegasikan tugas kepada kelas lain, maka perlu dilakukan tindakan Remove Middle Man.

Keuntungan

Kode yang lebih ramping.

Kapan Untuk Diabaibaikan

Jangan menghapus middle man yang telah dibuat dengan alasan tertentu:

Contoh

Masalah

                                
                                    
class Order {
    private OrderStatus orderStatus;

    public boolean isOrderShipped() {
        return orderStatus.isShipped();
    }
}

class OrderStatus {
    public boolean isShipped() {
       // Check if the order is shipped 
    }
}
                                            
                                
                            

Solusi

                                
                                    
class Order {
    private OrderStatus orderStatus;

    public boolean isShipped() {
        return orderStatus.isShipped();
    }
}

class OrderStatus {
    public boolean isShipped() {
       // Check if the order is shipped 
    }

    public boolean isNotShipped() {
        return !isShipped();
    }
}
                                                      
                                
                            

Dalam contoh ini, Kelas Order bertindak sebagai Middle Man dengan hanya mendelegasikan metode isShipped() ke objek OrderStatus.

kelas Order tidak lagi bertindak sebagai Middle Man karena memiliki tanggung jawab sendiri untuk memeriksa apakah pesanan sudah dikirim atau belum. Kelas OrderStatus juga menyediakan metode baru isNotShipped() untuk menghindari kebutuhan akan negasi dalam kode klien.