TestVagrant

Refactoring : Code Smells-Couplers

Refactoring: Code smell couplers

Blog

Refactoring : Code Smells-Couplers

A code smell is any characteristic in the source code of a program that possibly indicates a deeper problem.

As we have seen in previous blog Bloaters highlights about Long Methods, this blog focuses on Couplers.

Couplers are simply code smells that represent high coupling between classes or entire modules. In this article, we will concentrate on Feature Envy and Inappropriate Intimacy by using JavaScript as a programming language.

Feature Envy

Feature envy means that one class uses too many features of another class. This means that most of one class reference something in another class.

This is especially applicable to using fields from one in class in another class excessively.

For example, if we have the following

				
					class ContactInformation{

    constructor(streetName,city,state){
        this.streetName = streetName;
        this.city=city;
        this.state=state;
    }
}

class Customer{

    constructor(customerName,streetName,city,state){
        this.cusotmerName = customerName;
        this.contactInformation = new ContactInformation(streetName,city,state);
    }

    getCustomerContactInformation(){
        return `${this.contactInformation.streetName} ${this.contactInformation.city} 
        ${this.contactInformation.state}`
    }
}
				
			

The Customer class uses lots of fields from ContactInformation. We get most of the fields from ContactInformation in the Customer class when we don’t have to.

This breaks encapsulation in the ContactInformation class since we exposed the fields streeName,city and state when we don’t have to.

Instead, we should avoid using the streeName,city and state fields from the ContactInformation object in the Customer class and write a method in the ContactInformation class and call it in the Customer class as follows:

				
					class ContactInformation{

    constructor(streetName,city,state){
        this.streetName = streetName;
        this.city=city;
        this.state=state;
    }
    getContactInformation(){
        return `${this.streetName} ${this.city} ${this.state}`;
    }

}

class Customer{

    constructor(customerName,streetName,city,state){
        this.cusotmerName = customerName;
        this.contactInformation = new ContactInformation(streetName,city,state);
    }

    getCustomerContactInformation(){
        return this.contactInformation.getContactInformation();
    }
}
				
			

Inappropriate Intimacy

Sometimes you find a method in a class that needs to know too much about the inner workings or internal data of another class. 

We don’t want classes that depend on the implementation of the other classes because this means that we have to change both classes when the first class change.

There isn’t enough encapsulation of the fields or implementation of the methods.

Characteristics of Inappropriate Intimacy smell:

  • Classes used in the application become close buddies and spend more time with each other.
  • Each Class uses a significant number of methods and fields of other Class

For example, if we have the following:

				
					class ContactInformation{

    constructor(streetName,city,state,phoneNo){
        this.streetName = streetName;
        this.city=city;
        this.state=state;
        this.phoneNo = phoneNo;
    }
}

class Customer{

    constructor(customerName,streetName,city,state,phoneNo){
        this.customerName = customerName;
        this.contactInformation = new ContactInformation(streetName,city,state,phoneNo);
        this.notificationService = new NotificationService();
    }

    sendMail(customerName,contactInformation, message){   

        let mailBody = `${customerName} 
                        ${contactInformation.streetName} ${contactInformation.city}
                        ${contactInformation.phoneNo} 
                        Dear ${customerName} 
                        ${message}`;

        this.notificationService.notify(mailBody);
    }
}
				
			

In above example sendMail(customerName,contactInformation,message) method is using many details of ContactInformation, it would be better to move this logic from Customer class to ContactInformation class and create getCurrentMailAddress(customerName)

				
					class ContactInformation{

    constructor(streetName,city,state,phoneNo){
        this.streetName = streetName;
        this.city=city;
        this.state=state;
        this.phoneNo = phoneNo;
       
    }

    getCurrentMailAddress(customerName){
        let customerAddress = `${customerName} 
        ${this.streetName} ${this.city}
        ${this.phoneNo}`;

        return customerAddress;

    }
}

class Customer{

    constructor(customerName,streetName,city,state,phoneNo){
        this.customerName = customerName;
        this.contactInformation = new ContactInformation(streetName,city,state,phoneNo);
        this.notificationService = new NotificationService();
        
    }
    sendMail(customerName,message){   
       let customerAddress =  this.contactInformation.getCurrentMailAddress(customerName);
       let mailBody =`Dear ${customerName} 
                      ${message} `
       this.notificationService.notify(customerAddress,mailBody);
    }
}
				
			

If you read both code smells together it may confuse you at times, here is one line summary:

Feature Envy is when a method uses more public features of another class than it does of its own.

Inappropriate Intimacy is about a class consuming data that should be encapsulated from another class.

Happy Reading…

Other Related Articles

Scroll to Top