ฉันจะย้อนกลับไปที่นี่ คุณกำลังจดจ่อกับรายละเอียดที่พิถีพิถันของรหัส แต่ไม่มีภาพใหญ่ขึ้น ลองมาดูตัวอย่างหนึ่งในลูปของคุณ:
int offset = 0;
while(true)
{
Record r = Read(offset);
if(r == null)
{
break;
}
// do work
offset++;
}
อะไรคือความหมายของรหัสนี้หรือไม่? ความหมายคือ "ทำงานบางอย่างกับแต่ละระเบียนในไฟล์" แต่นั่นไม่ใช่สิ่งที่รหัสดูเหมือนว่า รหัสดูเหมือนว่า "รักษาออฟเซ็ตเปิดไฟล์ป้อนลูปโดยไม่มีเงื่อนไขสิ้นสุดอ่านเร็กคอร์ดทดสอบความว่างเปล่า" ทั้งหมดก่อนที่เราจะไปทำงาน! คำถามที่คุณควรถามคือ " ฉันจะทำให้ลักษณะที่ปรากฏของรหัสนี้ตรงกับความหมายได้อย่างไร " รหัสนี้ควรเป็น:
foreach(Record record in RecordsFromFile())
DoWork(record);
ตอนนี้โค้ดอ่านตามความตั้งใจ เฉพาะกิจกลไกของคุณจากความหมายของคุณ ในรหัสต้นฉบับของคุณคุณรวมกลไก - รายละเอียดของวง - กับความหมาย - งานที่ทำกับแต่ละระเบียน
RecordsFromFile()
ตอนนี้เรามีการดำเนินการ อะไรคือวิธีที่ดีที่สุดในการนำไปใช้ ใครสน? นั่นไม่ใช่รหัสที่ทุกคนกำลังดู มันเป็นรหัสกลไกพื้นฐานและมีความยาวสิบบรรทัด เขียนได้ตามที่คุณต้องการ แล้วเรื่องนี้ล่ะ
public IEnumerable<Record> RecordsFromFile()
{
int offset = 0;
while(true)
{
Record record = Read(offset);
if (record == null) yield break;
yield return record;
offset += 1;
}
}
ตอนนี้เรากำลังจัดการลำดับของเร็กคอร์ดที่คำนวณอย่างเกียจคร้านทุกประเภทของสถานการณ์เป็นไปได้:
foreach(Record record in RecordsFromFile().Take(10))
DoWork(record);
foreach(Record record in RecordsFromFile().OrderBy(r=>r.LastName))
DoWork(record);
foreach(Record record in RecordsFromFile().Where(r=>r.City == "London")
DoWork(record);
และอื่น ๆ
เมื่อใดก็ตามที่คุณเขียนลูปให้ถามตัวเองว่า "ลูปนี้อ่านเหมือนกลไกหรือชอบความหมายของโค้ดหรือไม่" หากคำตอบคือ "เหมือนกลไก" ให้ลองย้ายกลไกนั้นไปยังวิธีการของตัวเองแล้วเขียนรหัสเพื่อให้ความหมายชัดเจนยิ่งขึ้น