Test Observability & Engineering effectiveness
“Engineering Effectiveness” has been a central topic of discussion and focus this year
Testing across all interfaces, platforms and architectural components
Product test engineering, Shift-Left testing and digital transformation
Automate tests across all interfaces, platforms and horizontal scaling
Generative AI, Flutter, React Native, Micro-services, Micro-frontends & TestOps
Measure and enhance the efficiency & effectiveness of testing teams & solutions
Offshore Testing Setup as a Service, platform engineering and Modernisation
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 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();
}
}
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.
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…
“Engineering Effectiveness” has been a central topic of discussion and focus this year
With us, you’re not just a part of a company; you’re part of a movement dedicated to pushing boundaries, breaking barriers, and achieving the extraordinary.
Otaku 2.0 sought to redefine the way we approach testing, celebrate the spirit of innovation, and pave the way for a brighter future in tech.