:bathtub: 适用于 .NET 的清晰代码概念和工具
If you liked clean-code-dotnet project or if it helped you, please give a star :star: for this repository. That will not only help strengthen our .NET community but also improve skills about the clean code for .NET developers in around the world. Thank you very much :+1:
Check out my blog or say hi on Twitter!
Software engineering principles, from Robert C. Martin's book Clean Code, adapted for .NET/.NET Core. This is not a style guide. It's a guide to producing readable, reusable, and refactorable software in .NET/.NET Core.
Not every principle herein has to be strictly followed, and even fewer will be universally agreed upon. These are guidelines and nothing more, but they are ones codified over many years of collective experience by the authors of Clean Code.
Inspired from clean-code-javascript and clean-code-php lists.
Bad:
int d;Good:
int daySinceModification;Name the variable to reflect what it is used for.
Bad:
var dataFromDb = db.GetFromService().ToList();Good:
var listOfEmployee = _employeeService.GetEmployees().ToList();Hungarian Notation restates the type which is already present in the declaration. This is pointless since modern IDEs will identify the type.
Bad:
int iCounter;
string strFullName;
DateTime dModifiedDate;Good:
int counter;
string fullName;
DateTime modifiedDate;Hungarian Notation should also not be used in paramaters.
Bad:
public bool IsShopOpen(string pDay, int pAmount)
{
// some logic
}Good:
public bool IsShopOpen(string day, int amount)
{
// some logic
}Capitalization tells you a lot about your variables, functions, etc. These rules are subjective, so your team can choose whatever they want. The point is, no matter what you all choose, just be consistent.
Bad:
const int DAYS_IN_WEEK = 7;
const int daysInMonth = 30;
var songs = new List<string> { 'Back In Black', 'Stairway to Heaven', 'Hey Jude' };
var Artists = new List<string> { 'ACDC', 'Led Zeppelin', 'The Beatles' };
bool EraseDatabase() {}
bool Restore_database() {}
class animal {}
class Alpaca {}Good:
const int DaysInWeek = 7;
const int DaysInMonth = 30;
var songs = new List<string> { 'Back In Black', 'Stairway to Heaven', 'Hey Jude' };
var artists = new List<string> { 'ACDC', 'Led Zeppelin', 'The Beatles' };
bool EraseDatabase() {}
bool RestoreDatabase() {}
class Animal {}
class Alpaca {}It will take time to investigate the meaning of the variables and functions when they are not pronounceable.
Bad:
public class Employee
{
public Datetime sWorkDate { get; set; } // what the heck is this
public Datetime modTime { get; set; } // same here
}Good:
public class Employee
{
public Datetime StartWorkingDate { get; set; }
public Datetime ModificationTime { get; set; }
}Use Camelcase Notation for variable and method paramaters.
Bad:
var employeephone;
public double CalculateSalary(int workingdays, int workinghours)
{
// some logic
}Good:
var employeePhone;
public double CalculateSalary(int workingDays, int workingHours)
{
// some logic
}People who read your code are also programmers. Naming things right will help everyone be on the same page. We don't want to take time to explain to everyone what a variable or function is for.
Good
…Too many if else statements can make the code hard to follow. Explicit is better than implicit.
Bad:
public bool IsShopOpen(string day)
{
if (!string.IsNullOrEmpty(day))
{
day = day.ToLower();
if (day == "friday")
{
return true;
}
else if (day == "saturday")
{
return true;
}
else if (day == "sunday")
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}Good:
public bool IsShopOpen(string day)
{
if (string.IsNullOrEmpty(day))
{
return false;
}
string[] openingDays = ["friday", "saturday", "sunday"];
return openingDays.Any(d => d == day.ToLower());
}Bad:
public long Fibonacci(int n)
{
if (n < 50)
{
if (n != 0)
{
if (n != 1)
{
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
else
{
return 1;
}
}
else
{
return 0;
}
}
else
{
throw new System.Exception("Not supported");
}
}Good:
public long Fibonacci(int n)
{
if (n == 0)
{
return 0;
}
if (n == 1)
{
return 1;
}
if (n > 50)
{
throw new System.Exception("Not supported");
}
return Fibonacci(n - 1) + Fibonacci(n - 2);
}Don’t force the reader of your code to translate what the variable means. Explicit is better than implicit.
Bad:
var l = new[] { "Austin", "New York", "San Francisco" };
for (var i = 0; i < l.Count(); i++)
{
var li = l[i];
DoStuff();
DoSomeOtherStuff();
// ...
// ...
// ...
// Wait, what is `li` for again?
Dispatch(li);
}Good:
var locations = ["Austin", "New York", "San Francisco"];
foreach (var location in locations)
{
DoStuff();
DoSomeOtherStuff();
// ...
// ...
// ...
Dispatch(location);
}Magic strings are string values that are specified directly within application code that have an impact on the application’s behavior. Frequently, such strings will end up being duplicated within the system, and since they cannot automatically be updated using refactoring tools, they become a common source of bugs when changes are made to some strings but not others.
Bad
if (userRole == "Admin")
{
// logic in here
}Good
const string ADMIN_ROLE = "Admin"
if (userRole == ADMIN_ROLE)
{
// logic in here
}Using this we only have to change in centralize place and others will adapt it.
Don't add unneeded contextIf your class/object name tells you something, don't repeat that in your variable name.
Bad:
public class Car
{
public string CarMake { get; set; }
public string CarModel { get; set; }
public string CarColor { get; set; }
//...
}Good:
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public string Color { get; set; }
//...
}Bad:
var ymdstr = DateTime.UtcNow.ToString("MMMM dd, yyyy");Good:
var currentDate = DateTime.UtcNow.ToString("MMMM dd, yyyy");Bad:
GetUserInfo();
GetUserData();
GetUserRecord();
GetUserProfile();Good:
GetUser();We will read more code than we will ever write. It's important that the code we do write is readable and searchable. By not naming variables that end up being meaningful for understanding our program, we hurt our readers. Make your names searchable.
Bad:
// What the heck is data for?
var data = new { Name = "John", Age = 42 };
var stream1 = new MemoryStream();
var ser1 = new DataContractJsonSerializer(typeof(object));
ser1.WriteObject(stream1, data);
stream1.Position = 0;
var sr1 = new StreamReader(stream1);
Console.Write("JSON form of Data object: ");
Console.WriteLine(sr1.ReadToEnd());Good:
var person = new Person
{
Name = "John",
Age = 42
};
var stream2 = new MemoryStream();
var ser2 = new DataContractJsonSerializer(typeof(Person));
ser2.WriteObject(stream2, data);
stream2.Position = 0;
var sr2 = new StreamReader(stream2);
Console.Write("JSON form of Data object: ");
Console.WriteLine(sr2.ReadToEnd());Bad:
var data = new { Name = "John", Age = 42, PersonAccess = 4};
// What the heck is 4 for?
if (data.PersonAccess == 4)
{
// do edit ...
}Good:
public enum PersonAccess : int
{
ACCESS_READ = 1,
ACCESS_CREATE = 2,
ACCESS_UPDATE = 4,
ACCESS_DELETE = 8
}
var person = new Person
{
Name = "John",
Age = 42,
PersonAccess= PersonAccess.ACCESS_CREATE
};
if (person.PersonAccess == PersonAccess.ACCESS_UPDATE)
{
// do edit ...
}Bad:
const string Address = "One Infinite Loop, Cupertino 95014";
var cityZipCodeRegex = @"/^[^,\]+[,\\s]+(.+?)\s*(\d{5})?$/";
var matches = Regex.Matches(Address, cityZipCodeRegex);
i搜索可用名字 Part1 在良好代码部分使用了不正确的变量
"功能"部分"功能只应具有一个抽象层次"段中的拼写错误
DRY 部分的 ShowList 函数没有返回列表
为 <details> 元素添加 id,以便共享指定规则的 URL
SOLID. Liskov 替换原则 (LSP)。示例不正确。
从 https://csharpcodingguidelines.com 添加一些部分
请在本仓中添加包含 cs 示例的 vs 项目
对象和数据结构。使对象具有私有/受保护的成员
避免条件语句
CleanCodeDotnet