Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
C# and .NET Core Test-Driven Development

You're reading from   C# and .NET Core Test-Driven Development Dive into TDD to create flexible, maintainable, and production-ready .NET Core applications

Arrow left icon
Product type Paperback
Published in May 2018
Publisher
ISBN-13 9781788292481
Length 300 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Ayobami Adewole Ayobami Adewole
Author Profile Icon Ayobami Adewole
Ayobami Adewole
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Exploring Test-Driven Development FREE CHAPTER 2. Getting Started with .NET Core 3. Writing Testable Code 4. .NET Core Unit Testing 5. Data-Driven Unit Tests 6. Mocking Dependencies 7. Continuous Integration and Project Hosting 8. Creating Continuous Integration Build Processes 9. Testing and Packaging the Application 10. Other Books You May Enjoy

What we can do to prevent bad code

Writing clean code requires a conscious effort of maintaining professionalism and following best industry standards throughout the stages of the software development process. Bad code should be avoided right from the onset of software project development, because the accumulation of bad debt through bad code can slow down software project completion and create future issues after the software has been deployed to production.

To avoid bad code, you have to be lazy, as the general saying goes that lazy programmers are the best and smartest programmers because they hate repetitive tasks, such as having to go back to fix issues that could have been prevented. Try to use programming styles and approaches that avoid writing bad code, to avoid having to rewrite your code in order to fix avoidable issues, bugs, or to pay technical debts.

Loose coupling

Loose coupling is the direct opposite of tight coupling. This is a good object-oriented programming practice of separation of concerns by allowing components to have little or no information of the internal workings and implementation of other components. Communication is done through interfaces. This approach allows for an easy substitution of components without many changes to the entire code base. The sample code in the Tight coupling section can be refactored to allow loose coupling:

//The dependency injection would be done using Ninject
public ISmppManager smppManager { get; private set; }

public void SendSMS()
{
smppManager.SendMessage("0802312345","Hello", "John");
}

public class SmppManager
{
private string sourceAddress;
private SmppClient smppClient;

public SmppManager()
{
smppClient = new SmppClient();
smppClient.Start();
}

public void SendMessage(string recipient, string message, string senderName)
{
// send message using referenced library
}
}
public interface ISmppManager
{
void SendMessage(string recipient, string message, string senderName);
}

Sound architecture and design

Bad code can be avoided through the use of a good development architecture and design strategy. This will ensure that development teams and organizations have a high-level architecture, strategy, practices, guidelines, and governance plans that team members must follow to prevent cutting corners and avoiding bad code throughout the development process.

Through continuous learning and improvement, software development team members can develop thick skins towards writing bad code. The sample code snippet in the Bad or broken designs section can be refactored to be thread-safe and avoid thread-related issues, as shown in the following code:

public class SMTPGateway
{
private static SMTPGateway smtpGateway=null;
private static object lockObject= new object();

private SMTPGateway()
{
}

public static SMTPGateway SMTPGatewayObject
{
get
{
lock (lockObject)
{
if (smtpGateway==null)
{
smtpGateway = new SMTPGateway();
}
}
return smtpGateway;
}
}
}

Preventing and detecting code smell

Programming styles and coding formats that result in code smell should be avoided. By adequately paying attention to the details, bad code pointers discussed in the Code smell section should be avoided. The replicated lines of code in the two methods of the source code mentioned in the Code smell section can be refactored to a third method. This avoids replication of code and allows for easy modifications:

[HttpGet]
public ActionResult GetAllTransactions()
{
var yearsAndMonths=GetYearsAndMonths();
ViewBag.Transactions= GetTransactions(yearsAndMonths.Item1,yearsAndMonths.Item2);
return View();
}

[HttpGet]
public ActionResult SearchTransactions()
{
var yearsAndMonths=GetYearsAndMonths();
ViewBag.Years = yearsAndMonths.Item1;
ViewBag.Months = yearsAndMonths.Item2;
return View();
}

private (List<string>, List<string>) GetYearsAndMonths(){
List<string> years = new List<string>();
for (int i = DateTime.Now.Year; i >= 2015; i--)
years.Add(i.ToString());
List<string> months = new List<string>();
for (int j = 1; j <= 12; j++)
months.Add(j.ToString());
return (years,months);
}

Also, the method with a long list of parameters in the Code smell section can be refactored to use C# Plain Old CLR Object (POCO) for clarity and reusability:

public void ProcessTransaction(Transaction transaction)
{
//Do something
}

public class Transaction
{
public string Username{get;set;}
public string Password{get;set;}
public float TransactionAmount{get;set;}
public string TransactionType{get;set;}
public DateTime Time{get;set;}
public bool CanProcess{get;set;}
public bool RetryOnfailure{get;set;}
}

Development teams should have guidelines, principles, and coding conventions and standards developed jointly by the team members and should be constantly updated and refined. These, when used effectively, will prevent code smell in the software code base and allow for the easy identification of potential bad code by team members.

C# coding conventions

Using the guidelines in C# coding conventions facilitates the mastery of writing clean, readable, easy to modify, and maintainable code. Use variable names that are descriptive and represent what they are used for, as shown in the following code:

int accountNumber;

string firstName;

Also, having more than one statement or declaration on a line clogs readability. Comments should be on a new line and not at the end of the code. You can read more about C# coding conventions at: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions.

Succinct and proper documentation

You should always try to write self-documenting code. This can be achieved through good programming style. Write code in such a manner that your classes, methods, and other objects are self-documenting. A new developer should be able to pick your code and not have to be stressed out before understanding what the code does and its internal structure.

Coding elements should be descriptive and meaningful to provide an insight to the reader. In situations where you have to document a method or class to provide further clarity, adopt the Keep It Simple Short (KISS) approach, briefly stating the reasons for a certain decision. Check the following code snippet; nobody wants to have to read two pages of documentation for a class containing 200 lines of code:

///
/// This class uses SHA1 algorithm for encryption with randomly generated salt for uniqueness
///
public class AESEncryptor
{
//Code goes here
}
KISS also known as Keep it Simple, Stupid, is a design principle that states that most systems work at their best when they are kept simple rather than making them unnecessarily complex. The principle aims at aiding programmers to keep the code simple as much as possible, to ensure that code can be easily maintained in the future.

Why test-driven development?

Each time I enter a discussion with folks not practicing test-driven development, they mostly have one thing in common, which is that it consumes time and resources and it does not really give a return on investment. I usually reply to them by asking which is better, detecting bugs and potential bottlenecks and fixing them while the application is being developed or hotfixing bugs when the application is in production? Test-driven development will save you a lot of problems and ensure you produce robust and issue-free applications.

Building for longevity

To avoid future problems resulting from issues when making modifications to a system in production as a result of changes in user requirements, as well as bugs which get exposed because of inherent bad code in a code base and accumulated technical debt, you need to have the mindset of developing with the future in mind and embracing changes.

Use flexible patterns and always employ good object-oriented development and design principles when writing code. The requirements of most software projects change over their life cycles. It is wrong to assume that a component or part might not change, so try and put a mechanism in place to allow the application to be graceful and accept future changes.

You have been reading a chapter from
C# and .NET Core Test-Driven Development
Published in: May 2018
Publisher:
ISBN-13: 9781788292481
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime