Introduction
A class in C# is considered a referenced type, within classes one can create Properties, Methods, Constructors, and other components available within the programing language. Developers can create several methods in a class however, a concrete class cannot be created within a method in C#. Therefore, classes are a level higher than methods and of extreme importance to clean code.
Class Organization
It is recommended to maintain minimal class organization when it comes to ordering the elements that composes a class. This consistency should be applied throughout all projects within an organization. When ordering elements in a class one could consider the order:
- Constants
- Variables
- Properties
- Constructor
- Methods
- 5-1. Public Methods
- 5-2. Protected Methods
- 5-3. Private Methods
I have not found any official rules or recommendations for ordering elements in C# code, but keeping a consistent order between classes in a project or solution is wise.
Class Size
Classes should be small, however to measure the size of a class, lines of code is not the only concern, the responsibilities should also be considered. Giving meaningful names to classes helps one to describe the responsibilities it has. Some names makes classes seem like it has generic or too much responsibility, as described in the following example:
Example 1:
public class PageManager{}
public class MasterTab{}
public class SuperAlgorithm{}
The SRP is part of the 'S' in the SOLID principles that composes of good practices in object oriented programing. It states that modules including classes should have single responsibility and only one reason to change. However it is common to see this principle violated. Uncle Bob states that
writing code that executes is not the same as developing clean code.
Dependency Inversion Principle (DIP)
In Object Oriented Programing (OOP), concrete classes contains implementation details and interfaces that includes the definitions of the services within a group.
Checkout the following code taken from the NLOG library, it has an example of a concrete implementation of the logging:
Example 2:
using NLog.Web;
using Microsoft.Extensions.Logging;
public static void Main(string[] args)
{
// NLog: setup the logger first to catch all errors
var logger = NLog.LogManager.Setup().RegisterNLogWeb().GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateWebHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
//NLog: catch setup errors
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
As displayed in Example 2, to depend on concrete implementations one would could setup a new instance of a logger every time it needs to be used. However NLog provides abstractions where Dependency injection can be configured as seen in the following code:
Example 3:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog(); // NLog: setup NLog for Dependency injection
using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("Index page says hello");
return View();
}
}
In Example 3 the Microsoft extension logging library injects the NLOG implementations. The power of this implementation is that it is easy to change logging technologies and its loosely coupled because the implementation does not depend on concrete implementation in this case NLOG it uses a generic logging interface.
Conclusion
When creating classes think about the impacts the class you are creating can have on the overall system. Creating abstractions such as interfaces is a good idea if the implementation details may change in the future. It also provides better testing functionalities where one could mock the abstractions.
References
- Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.
- https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-2
Top comments (0)