คอลเลกชันของแนวทางที่สมเหตุสมผลและแนวทางปฏิบัติที่ดีที่สุดในการเขียนรหัส C# ที่ทำความสะอาดอ่านง่ายเข้าใจได้และบำรุงรักษาได้
var เมื่อเหมาะสมและเป็นไปได้วัตถุประสงค์: การอ่านและความสะอาดที่ดีขึ้น
ดี
var httpClient = new HttpClient ( ) ;แย่
HttpClient httpClient = new HttpClient ( ) ; วัตถุประสงค์: การอ่านและความสะอาดที่ดีขึ้น
ดี
var user = new User
{
Username = "admin" ,
Age = 31
} ;แย่
var user = new User ( ) ;
user . Username = "admin" ;
user . Age = 31 ; string.Formatวัตถุประสงค์: ความสามารถในการอ่านและความหมายที่ดีขึ้น
ดี
var url = "http://localhost/api" ;
var resource = "users" ;
var path = $ " { url } / { resource } " ;แย่
var url = "http://localhost/api" ;
var resource = "users" ;
var path = string . Format ( "{0}/{1}" , url , resource ) ;วัตถุประสงค์: ไม่จำเป็นต้องหลบหนีอักขระ backslash
ดี
var path = @"C:UsersAdministratorDocuments" ;แย่
var path = "C: \ Users \ Administrator \ Documents" ;วัตถุประสงค์: refactoring อาจกลายเป็นฝันร้ายเมื่อมีการกระจายตัวอักษรสตริงทั่วสถานที่หลายครั้ง
ดี
const string error = "user_not_found" ;
Log . Error ( error ) ;
return BadRequest ( error ) ;แย่
Log . Error ( "user_not_found" ) ;
return BadRequest ( "user_not_found" ) ; xyz มันไร้สาระวัตถุประสงค์: การตัดชื่อตัวแปรที่สั้นลงไม่ได้เพิ่มค่าใด ๆ มันทำให้โค้ดอ่านและทำความเข้าใจได้ยากขึ้น
ดี
// Nice
var validationResult = validator . Validate ( ) ;
// Nice
var stringBuilder = new StringBuilder ( ) ;
// Nice
const string directorySeparator = "/" ;แย่
//
var res = validator . Validate ( ) ;
//
var sbd = new StringBuilder ( ) ;
// Seriously?
const string dsep = "/" ;วัตถุประสงค์: ทำให้รหัสอ่านดูแลรักษาและทำงานได้ง่ายขึ้นอย่างมาก
ดี
// The purpose of this class can be easily inferred
public class OrderManager
{
// Using "Is" or "Has" as prefix clearly indicates that a method returns a boolean value
public bool IsFulfilled ( Order order )
{
}
public bool HasPositions ( Order order )
{
}
// Using a verb clearly indicates that a method performs some action
public void ProcessOrder ( Order order )
{
}
public void CancelOrder ( Order order )
{
}
}แย่
// Purpose of this class can not be easily inferred
public class OrderHelper
{
// Unclear
public bool Fulfilled ( Order order )
{
}
// Unclear => users would likely expect a method that retrieves the positions of the order due to the verb "Get"
public bool GetPositions ( Order order )
{
}
// Unclear
public void Order ( Order order )
{
}
// Unclear
public void StopOrder ( Order order )
{
}
}วัตถุประสงค์: ทำให้รหัสยาวขึ้นโดยไม่จำเป็นและยากที่จะอ่านและเข้าใจ
ดี
// Clearly an interface
public interface IOrderManager { }
// Clearly a list of orders
private IList < Order > orders ;แย่
// Clearly an interface => no "Interface" postfix necessary
public interface IOrderManagerInterface { }
// Clearly a list of oders => no "List" postfix necessary
private IList < Order > orderList ;วัตถุประสงค์: การปฏิบัติแสดงให้เห็นว่าความคิดเห็นอาจล้าสมัยได้อย่างง่ายดายและรวดเร็วเมื่อฐานรหัสเติบโตและวิวัฒนาการ การมีฐานรหัสที่อธิบายตนเองมีส่วนช่วยในการบำรุงรักษาที่ดีขึ้นและลดความจำเป็นในการเขียนและรักษาความคิดเห็นที่ไม่เป็นประโยชน์ (นี่ไม่ได้หมายความว่าการเขียนความคิดเห็นล้าสมัย)
ดี
public class OrderManager
{
public void ProcessOrder ( Order order )
{
var items = order . GetItems ( ) ;
foreach ( var item in items )
{
var availability = item . GetAvailability ( ) ;
}
}
}แย่
public class OrderManager
{
public void ExecuteOrder ( Order order )
{
// Get all available items from the order
var data = order . GetData ( ) ;
foreach ( var x in data )
{
// Determine the availability of the item
var available = item . CheckAvailability ( ) ;
}
}
}วัตถุประสงค์: สอดคล้องกับ. NET Framework และอ่านง่ายขึ้น
ดี
public class JsonParser { }แย่
public class JSONParser { } วัตถุประสงค์: enum s ได้รับการแก้ไขเป็นรายบุคคลเสมอ ตัวอย่างเช่น EmploymentType.FullTime นั้นสะอาดกว่า EmploymentTypes.FullTime มากที่สุด นอกจากนี้คลาสมักจะแสดงอินสแตนซ์เดียวของวัตถุเช่น User แต่ละราย ข้อยกเว้น: บิตฟิลด์ enums
ดี
public enum EmploymentType
{
FullTime ,
PartTime
}
public class User
{
}แย่
public enum EmploymentTypes
{
FullTime ,
PartTime
}
public class Users
{
} วัตถุประสงค์: น้ำตาลวากยสัมพันธ์¯ (ツ) /¯
ดี
public class User
{
public string Username { get ; }
public int Age { get ; }
public string DisplayName => $ " { Username } ( { Age } )" ;
public User ( string username , int age )
{
Username = username ;
Age = age ;
}
}แย่
public class User
{
public string Username { get ; }
public int Age { get ; }
public string DisplayName
{
get
{
return $ " { Username } ( { Age } )" ;
}
}
public User ( string username , int age )
{
Username = username ;
Age = age ;
}
} จุดประสงค์: การรับรู้ที่ดีขึ้นเกี่ยวกับสิ่งที่ผิดพลาด ช่วยให้มีความแม่นยำมากขึ้นในระหว่างการบันทึกและการวิเคราะห์ข้อผิดพลาด
ดี
try
{
System . IO . File . Open ( path ) ;
}
catch ( FileNotFoundException ex )
{
// Specific
}
catch ( IOException ex )
{
// Specific
}
catch ( Exception ex )
{
// Default
}แย่
try
{
System . IO . File . Open ( path ) ;
}
catch ( Exception ex )
{
// SOMETHING went wrong
}Exception ด้วยตัวคุณเอง จุดประสงค์: การปฏิบัติที่แย่มาก Exception S ควรถูกโยนลงโดย. NET Framework เท่านั้น
ดี
public void ProcessOrder ( Order order )
{
if ( order == null )
{
throw new ArgumentNullException ( nameof ( order ) ) ;
}
}แย่
public void ProcessOrder ( Order order )
{
if ( order == null )
{
throw new Exception ( "Order is null." ) ;
}
} วัตถุประสงค์: การอ่านได้ดีขึ้น
ดี
private string _username ;แย่
private string mUsername__ ;
// OR
private string username ;
// OR
private string username_ ; วัตถุประสงค์: การอ่านที่ดีขึ้นช่วยประหยัดพื้นที่
ดี
public class JsonParser
{
private readonly string _json ;
public JsonParser ( string json )
{
_json = json ;
}
}แย่
public class JsonParser
{
private readonly string _json ;
public JsonParser ( string json )
{
_json = json ;
}
} วัตถุประสงค์: ป้องกันทรัพย์สินจากการเปลี่ยนแปลงโดยไม่ตั้งใจจากที่อื่นการทำนายพฤติกรรมของแอปพลิเคชันที่ดีขึ้น
ดี
public class JsonParser
{
public string Json { get ; }
public JsonParser ( string json )
{
Json = json ;
}
}แย่
public class JsonParser
{
public string Json { get ; set ; }
public JsonParser ( string json )
{
Json = json ;
}
}วัตถุประสงค์: ป้องกันการรวบรวมจากการเปลี่ยนแปลงจากที่อื่นการทำนายพฤติกรรมของแอปพลิเคชันที่ดีขึ้น
ดี
public class KeywordProvider
{
public IReadOnlyCollection < string > Keywords { get ; }
public KeywordProvider ( )
{
Keywords = new ReadOnlyCollection < string > ( new List < string >
{
"public" ,
"string"
} ) ;
}
}แย่
public class KeywordProvider
{
public IList < string > Keywords { get ; }
public KeywordProvider ( )
{
Keywords = new List < string >
{
"public" ,
"string"
} ;
}
} using บล็อกเสมอ วัตถุประสงค์: ทรัพยากรจะถูกกำจัดโดยอัตโนมัติเมื่อ using บล็อกเสร็จสิ้น
ดี
using ( var connection = new SqlConnection ( connectionString ) )
{
}แย่
try
{
var connection = new SqlConnection ( connectionString ) ;
}
finally
{
connection . Close ( ) ;
connection . Dispose ( ) ;
} วัตถุประสงค์: การอ่านได้ดีขึ้นการบำรุงรักษาง่ายขึ้นเมื่อต้องการสายอื่นภายในเงื่อนไข
ดี
if ( user . IsElevated )
{
// Do something
}แย่
if ( user . IsElevated )
// Do somethingวัตถุประสงค์: เพื่อให้คุณทราบว่าส่วนใดของข้อความมีตัวแปร
ดี
var filePath = @"C:tmpmy-file.txt" ;
try
{
var file = File . Open ( filePath ) ;
}
catch ( Exception ex )
{
// GOOD: Add [ ] to the variable
Log . Error ( $ "Could not open file [ { filePath } ]." , ex ) ;
}แย่
var filePath = @"C:tmpmy-file.txt" ;
try
{
var file = File . Open ( filePath ) ;
}
catch ( Exception ex )
{
Log . Error ( $ "Could not open file { filePath } ." , ex ) ;
}วัตถุประสงค์: เพื่อให้สามารถกรองข้อยกเว้นในบางกรณี (ตัวอย่างเช่นในส่วนต่อประสานผู้ใช้เนื่องจากการติดตามสแต็กทั้งหมดนั้นไร้ประโยชน์สำหรับผู้ใช้)
ดี
try
{
var file = File . Open ( @"C:tmpmy-file.txt" ) ;
}
catch ( Exception ex )
{
// Use appropriate signature of your logger to include the exception as separate parameter
Log . Error ( "Could not open file." , ex ) ;
}แย่
try
{
var file = File . Open ( @"C:tmpmy-file.txt" ) ;
}
catch ( Exception ex )
{
// Strictly AVOID this. The exception is added directly to the log message, which makes it impossible to filter the exception
Log . Error ( $ "Could not open file: { ex } " ) ;
}