ฉันสามารถใช้ขั้นตอนและมาตรการใดในการป้องกันการเยื้องในโค้ดของฉัน
ฉันสามารถใช้ขั้นตอนและมาตรการใดในการป้องกันการเยื้องในโค้ดของฉัน
คำตอบ:
การเยื้องที่ลึกมักจะไม่เกิดปัญหาหากทุกฟังก์ชั่น / วิธีในโปรแกรมของคุณทำสิ่งใดสิ่งหนึ่งเพียงอย่างเดียว บางครั้งอาจจำเป็นต้องวางเงื่อนไขบางระดับลึก แต่ฉันสามารถพูดได้ว่าฉันเขียนโค้ดเว้าลึกเพียงไม่กี่ครั้งในการเข้ารหัส 12 ปีขึ้นไป
สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือแยกวิธี:
int Step1(int state)
{
if (state == 100)
{
return Step2(state);
}
else
{
return Step3(state);
}
}
int Step2(int state)
{
if (state != 100)
{
throw new InvalidStateException(2, state);
}
// ....
}
if
-conditions ที่ซับซ้อน เมื่อถึงจุดสุดยอดคุณจะพบกับ pseudocode ที่สามารถเรียกใช้งานได้
else
บล็อคที่ไม่จำเป็น
บางทีคุณอาจพิจารณาคำสั่งป้องกันหรือไม่
แทน
public void DoSomething(int value){
if (someCondition){
if(someOtherCondition){
if(yetAnotherCondition){
//Finally execute some code
}
}
}
}
ทำ
public void DoSomething(int value){
if(!(someCondition && someOtherCondition && yetAnotherCondition)){
return;
//Maybe throw exception if all preconditions must be true
}
//All preconditions are safe execute code
}
หากคุณเคยได้รับโอกาสฉันขอแนะนำให้คุณอ่าน Code Complete โดย Steve McConnell เขาได้รับคำแนะนำที่ดีมากมายในหัวข้อเหล่านี้
http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ "คำสั่งป้องกัน" ดูที่: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses
Invert ของคุณif
s
แทน:
if (foo != null)
{
something;
something;
if (x)
{
something;
}
something;
}
else
{
boohoo;
}
ฉันจะเขียน:
if (foo == null)
{
boohoo;
return;
}
something;
something;
if (x)
{
something;
}
something;
เช่นเดียวกับบล็อกif
- else
หากelse
ซ้อนกันน้อยกว่าหรือน้อยกว่าให้เปลี่ยนกลับเป็นค่าเดิม
ตรวจสอบค่าพารามิเตอร์ในที่เดียว
ตรวจสอบพารามิเตอร์ทั้งหมดสำหรับค่าที่ผิดกฎหมายทันทีที่คุณเข้าสู่วิธีการของคุณจากนั้นดำเนินการต่อเพื่อทราบว่าคุณปลอดภัย มันทำให้รหัสที่อ่านได้มากขึ้น แต่ยังช่วยให้คุณซ้อนบล็อกตามเงื่อนไขในภายหลังและกระจายการตรวจสอบเหล่านี้ทั่วรูทีนย่อย
If
ที่จุดเริ่มต้นของรหัสที่หยุดการไหลของการดำเนินการเนื่องจากเงื่อนไขบางอย่างที่ไม่ได้พบกันยังเป็นที่รู้จักกันเป็นอนุประโยคปกป้องเช่น @JasonTuran ชี้ให้เห็น และดูเหมือนว่าจะใกล้เคียงกับชื่อที่แตกต่าง
โดยทั่วไปฉันได้เห็นว่ารหัสเว้าลึกมักจะเป็นรหัสที่มีปัญหา หากคุณกำลังประสบปัญหานี้ให้ถอยกลับและประเมินว่าฟังก์ชันของคุณกำลังทำหลายสิ่งมากเกินไปหรือไม่
ในเวลาเดียวกันเพื่อตอบคำถามของคุณหากมีความจำเป็นสำหรับการเยื้องที่ลึกฉันจะแนะนำให้คุณปล่อยให้มันอยู่ที่นั่น ด้วยเหตุผลง่ายๆว่าในรหัสดังกล่าวการเยื้องจะช่วยได้เนื่องจากมีแนวโน้มว่าจะเป็นโค้ดที่ยาวมาก
แบ่งส่วนประกอบที่ซ้อนกัน (โดยเฉพาะอย่างยิ่งที่ซ้ำแล้วซ้ำอีก) ออกเป็นฟังก์ชั่นแยกต่างหาก (ซึ่งจะง่ายกว่านี้หากภาษาของคุณรองรับการปิด) หรือแทนที่ชุดของลูปซ้อนที่มีการเรียกซ้ำ
นอกจากนี้เยื้องสองช่องว่างแทนสี่
ฉันไม่เห็นว่าการลบรอยลึกเป็นปัญหาเชิงหมวดหมู่ที่จะลบออก
โดยทั่วไปแล้วแทนที่จะเป็น ifs ซ้อนกันฉันชอบที่จะเขียนคำสั่งตรรกะ:
if (foo && bar && baz)
ค่อนข้างมากกว่า
if foo
if bar
if baz
ฉันไม่เชื่อตัวเอง แต่ตาม Code Complete นี่เป็นสถานที่ที่เหมาะสมที่จะใช้break
(ถ้าทีมของคุณอยู่บนเครื่อง) ฉันคิดว่านี่เป็นที่ยอมรับมากขึ้นกับโปรแกรมเมอร์ C ++ แต่ที่break
ใช้ในswitch
งบมากกว่าที่มีกับโปรแกรมเมอร์ Delphi ที่break
ใช้เฉพาะเมื่อคุณไม่รู้สึกเหมือนเขียนwhile
วน
การเยื้องเป็นความคิดที่จะต่อสู้แน่นอน สิ่งที่ฉันเรียนรู้ที่จะทำคือการแบ่งวิธีการออกเป็นชิ้น ๆ ก่อนจากนั้นใช้เคล็ดลับแปลก ๆ เพื่อข้ามชิ้นส่วนต่อไปนี้ถ้าชิ้นหนึ่งล้มเหลว นี่คือตัวอย่าง:
แทน :
{if (networkCardIsOn() == true)
{if (PingToServer() == true)
{if (AccesLogin(login,pass) == true)
{if (nextCondition == true)
...
}
}
}
ฉันกำลังเขียน:
{vbContinue = true;
if (vbContinue) {
vbContinue = networkCardIsOn();
if (vbContinue == false) {
code to Handle This Error();
}
}
if (vbContinue) {
vbContinue = PingToServer();
if (vbContinue == false) {
code to HandleThisError2();
}
}
if (vbContinue) {
vbContinue = AccesLogin(login,pass);
if (vbContinue == false) {
HandleThisErrorToo();
}
}
...
นี่เป็นครั้งแรกที่ฉันรู้สึกแปลก ๆ แต่เนื่องจากฉันใช้สิ่งนี้ค่าบำรุงรักษาจึงถูกแบ่งครึ่งและสมองของฉันก็เย็นลงในตอนท้ายของวัน
ในความเป็นจริงได้รับการแนะนำโดย "เทคนิค" นี้คือความซับซ้อนของรหัสจะถูกแบ่งออกจริงๆเพราะรหัสมีความหนาแน่นน้อยกว่า
ในขณะที่อ่านรหัสคุณไม่จำเป็นต้องจดจำอะไรเกี่ยวกับเงื่อนไขในอดีต: ถ้าคุณอยู่ที่จุดนั้น X ในรหัสขั้นตอนก่อนหน้านี้จะถูกส่งผ่านและประสบความสำเร็จ
กำไรอีกอย่างก็คือ "ทางหนีและเงื่อนไข" จากทั้งหมดที่ซ้อนอยู่ใน "if-else" เหล่านั้นจะง่ายขึ้น