Code Smell - Duplicate Code
Because every line of code that goes into the codebase needs to be maintained, duplicated code decreases productivity. In addition, when Engineers update one part of the code, they must make the exact change to multiple locations. Then there's the risk that someone will miss one section and introduce a bug.
"It's not a question of if you'll forget about the multiple places to maintain, it's when." - The Pragmatic Programmer by Andrew Hunt, David Thomas.
Duplicated code stems from programmers copying and pasting code or having a poor understanding of how to apply abstraction. Fixing duplication starts by recognising where the duplication exists. Then, you can follow the DRY (Don't Repeat Yourself) software engineering principle and extract similar code into a method, service or class.
Here is an example C# code that contains duplicate code logic for sending email:
using System;
using System.Net.Mail;
namespace EmailService
{
public class EmailSender
{
private SmtpClient _smtpClient;
private string _emailFrom;
public EmailSender(string smtpServer, int smtpPort, string emailFrom, string smtpUsername, string smtpPassword)
{
_smtpClient = new SmtpClient(smtpServer, smtpPort);
_smtpClient.Credentials = new System.Net.NetworkCredential(smtpUsername, smtpPassword);
_emailFrom = emailFrom;
}
public bool SendEmail(string emailTo, string emailSubject, string emailBody)
{
return SendEmail(emailTo, emailSubject, emailBody, null);
}
public bool SendEmail(string emailTo, string emailSubject, string emailBody, string attachmentFilePath)
{
try
{
var mailMessage = new MailMessage(_emailFrom, emailTo, emailSubject, emailBody);
mailMessage.IsBodyHtml = true;
if (!string.IsNullOrEmpty(attachmentFilePath))
{
var attachment = new Attachment(attachmentFilePath);
mailMessage.Attachments.Add(attachment);
}
_smtpClient.Send(mailMessage);
return true;
}
catch (Exception ex)
{
// Handle exception here
return false;
}
}
}
}
In this updated version, we've created an overloaded version of the SendEmail
method that takes an additional parameter for the attachment file path. The original SendEmail
method now simply calls the overloaded version with a null
attachment file path.
using System;
using System.Net.Mail;
namespace EmailService
{
public class EmailSender
{
private SmtpClient _smtpClient;
private string _emailFrom;
public EmailSender(string smtpServer, int smtpPort, string emailFrom, string smtpUsername, string smtpPassword)
{
_smtpClient = new SmtpClient(smtpServer, smtpPort);
_smtpClient.Credentials = new System.Net.NetworkCredential(smtpUsername, smtpPassword);
_emailFrom = emailFrom;
}
public bool SendEmail(string emailTo, string emailSubject, string emailBody)
{
return SendEmail(emailTo, emailSubject, emailBody, null);
}
public bool SendEmail(string emailTo, string emailSubject, string emailBody, string attachmentFilePath)
{
try
{
var mailMessage = new MailMessage(_emailFrom, emailTo, emailSubject, emailBody);
mailMessage.IsBodyHtml = true;
if (!string.IsNullOrEmpty(attachmentFilePath))
{
var attachment = new Attachment(attachmentFilePath);
mailMessage.Attachments.Add(attachment);
}
_smtpClient.Send(mailMessage);
return true;
}
catch (Exception ex)
{
// Handle exception here
return false;
}
}
}
}
By doing this, we've eliminated the duplicate code and consolidated the logic for sending emails with or without attachments into a single method. This adheres to the DRY principle and makes the code more maintainable and easier to read.