แยกการคำนวณค่าส่งคืนและคำสั่งส่งคืนในวิธีเดียวหรือไม่


26

ฉันได้พูดคุยกับเพื่อนร่วมงานเกี่ยวกับการทำลายreturnคำสั่งและคำสั่งที่คำนวณค่าส่งคืนในสองบรรทัด

ตัวอย่างเช่น

private string GetFormattedValue()
{
    var formattedString = format != null ? string.Format(format, value) : value.ToString();
    return formattedString;
}

แทน

private string GetFormattedValue()
{
    return format != null ? string.Format(format, value) : value.ToString();
}

รหัสฉลาดฉันไม่เห็นคุณค่าในตัวแปรแรก สำหรับฉันหลังมีความชัดเจนโดยเฉพาะอย่างยิ่งสำหรับวิธีการที่สั้น ข้อโต้แย้งของเขาไม่ว่าอะไรก็ตามที่ตัวแปรในอดีตนั้นง่ายต่อการตรวจแก้จุดบกพร่อง - ซึ่งค่อนข้างจะเป็นข้อดีเล็กน้อยเนื่องจาก VisualStudio ช่วยให้เราสามารถตรวจสอบข้อความได้อย่างละเอียดมากเมื่อการดำเนินการหยุดลงเนื่องจากจุดแตกหัก

คำถามของฉันคือถ้ามันยังคงเป็นจุดที่ถูกต้องในการเขียนรหัสที่ชัดเจนน้อยลงเพียงเพื่อให้การดีบักการเหลือบง่ายขึ้น? มีข้อโต้แย้งเพิ่มเติมสำหรับตัวแปรที่มีการคำนวณแยกและreturnคำสั่งหรือไม่


18
ไม่ทำงานกับ VS แต่จะถือว่าคุณไม่สามารถตั้งค่าเบรกพอยต์แบบมีเงื่อนไขบนนิพจน์ที่ซับซ้อน (หรือป้อนได้ยาก) ดังนั้นอาจจะกำหนดและส่งกลับไปยังคำสั่งแยกต่างหากเพื่อความสะดวก คอมไพเลอร์อาจจะเกิดขึ้นกับรหัสเดียวกันทั้งสองอย่างใด
tofro

1
สิ่งนี้อาจขึ้นอยู่กับภาษาโดยเฉพาะอย่างยิ่งในภาษาที่ตัวแปรมีพฤติกรรมวัตถุ (อาจซับซ้อน) แทนที่จะเป็นตัวชี้พฤติกรรม คำสั่งของ @Paul K อาจเป็นจริงสำหรับภาษาที่มีลักษณะการทำงานของตัวชี้ภาษาที่วัตถุมีลักษณะการทำงานที่เรียบง่ายและภาษาที่มีคอมไพเลอร์ที่มีคุณภาพสูงและเป็นผู้ใหญ่
MSalters

4
"เนื่องจาก VisualStudio ช่วยให้เราสามารถตรวจสอบคำสั่งได้อย่างละเอียดมากเมื่อการดำเนินการหยุดลงเนื่องจากจุดพัก" - เป็นเช่นนั้น ดังนั้นคุณจะได้รับค่าตอบแทนอย่างไรถ้าฟังก์ชันส่งคืนโครงสร้างที่มีสมาชิกมากกว่าหนึ่งคน? (และการสนับสนุนสำหรับคุณลักษณะนั้น ๆ นั้นดูดีที่สุดมีชุดค่าผสมมากมายที่คุณไม่ได้รับผลตอบแทนเลย)
Voo

2
การมี "การตรวจสอบข้อความอย่างละเอียดมาก ๆ " ในคนดีบั๊กใช้วันนี้เป็นตัวเลือกที่ไม่ดีในการเขียนรหัสเพื่อให้ง่ายต่อการดีบักในโปรแกรมดีบั๊กใด ๆ
เอียน

16
รบกวนเขาต่อไปโดยลดการทำงานของร่างกายทั้งหมดให้เป็นprivate string GetFormattedValue() => string.Format(format ?? "{0}", value);
Graham

คำตอบ:


46

การแนะนำตัวแปรอธิบายคือการปรับโครงสร้างที่รู้จักกันดีซึ่งบางครั้งสามารถช่วยให้การแสดงออกที่ซับซ้อนสามารถอ่านได้ดีขึ้น อย่างไรก็ตามในกรณีที่แสดง

  • ตัวแปรเพิ่มเติมไม่ได้ "อธิบาย" สิ่งใด ๆ ที่ไม่ชัดเจนจากชื่อวิธีการที่อยู่รอบ ๆ
  • คำสั่งจะได้รับอีกต่อไปดังนั้น (เล็กน้อย) อ่านได้น้อยลง

ยิ่งไปกว่านั้นดีบักเกอร์ Visual Studio รุ่นใหม่ยังสามารถแสดงค่าตอบแทนของฟังก์ชันในกรณีส่วนใหญ่โดยไม่ต้องแนะนำตัวแปรฟุ่มเฟือย (แต่ระวังมีบาง caveats ดูโพสต์ SO เก่าและคำตอบที่ต่างกัน )

ดังนั้นในกรณีเฉพาะนี้ฉันเห็นด้วยกับคุณอย่างไรก็ตามมีกรณีอื่น ๆ ที่ตัวแปรอธิบายสามารถปรับปรุงคุณภาพรหัสได้แน่นอน


ผมเห็นด้วยเช่นกันว่ามีแน่นอนเป็นกรณีที่มันมีประโยชน์อย่างไม่ต้องสงสัย
Paul Kertscher

2
ฉันมักจะใช้resultเป็นชื่อของตัวแปร ไม่นานกว่าการดีบักได้ง่ายขึ้น
edc65

26
@ edc65: ชื่อสามัญเช่นresult มักจะเพิ่มเสียงให้กับรหัสและไม่ค่อยจะเพิ่มการอ่านซึ่งเป็นจุดของคำตอบของฉัน สิ่งนี้สามารถพิสูจน์ได้ในบริบทที่ช่วยแก้ไขข้อบกพร่อง แต่ฉันจะหลีกเลี่ยงเมื่อใช้ดีบักเกอร์ที่ไม่ต้องการตัวแปรแยกต่างหาก
Doc Brown

6
@ Jonhanna เครื่องมือทางยาวตามฉัน ชื่อresultสื่อถึงข้อมูลที่เป็นค่าที่เกิดจากฟังก์ชันดังนั้นคุณจึงสามารถดูได้ก่อนที่ฟังก์ชันจะส่งคืน
edc65

1
@ edc65 แต่นั่นทำให้ดูมีประโยชน์ ดังนั้นเมื่อฉันอ่านรหัสของคุณฉันไม่ได้ตระหนักทันทีว่าไม่ใช่ ดังนั้นรหัสของคุณอ่านง่ายขึ้น
Jon Hanna

38

รับข้อเท็จจริงที่:

a) ไม่มีผลกระทบกับรหัสสุดท้ายเนื่องจากคอมไพเลอร์ปรับค่าตัวแปรให้เหมาะสม

b) การมีมันแยกต่างหากช่วยเพิ่มความสามารถในการดีบัก

ฉันได้ข้อสรุปเป็นการส่วนตัวว่าเป็นวิธีที่ดีที่จะแยกพวกเขาออก 99% ของเวลา

ไม่มีข้อเสียที่เป็นรูปธรรมในการทำเช่นนี้ อาร์กิวเมนต์ที่มันเป็นรหัส bloats เป็นชื่อเรียกผิดเพราะรหัสที่ bloated เป็นปัญหาเล็กน้อยเมื่อเปรียบเทียบกับรหัสที่อ่านไม่ได้หรือรหัสที่ยากต่อการแก้ไขข้อผิดพลาด นอกจากนี้วิธีนี้ไม่สามารถสร้างรหัสที่สับสนได้ซึ่งขึ้นอยู่กับผู้พัฒนาทั้งหมด


9
นี่คือคำตอบที่ถูกต้องสำหรับฉัน สิ่งนี้ทำให้การตั้งค่าเบรกพอยต์ได้ง่ายขึ้นและดูค่าเมื่อทำการดีบั๊กและไม่มีข้อเสียที่ฉันทราบ
Matthew James Briggs

สำหรับจุด b ใน Visual Studio Code เพียงแค่ใส่เบรกพอยต์ในการส่งคืนแล้วเพิ่มการแสดงออก: GetFormattedValue () และที่จะแสดงผลลัพธ์เมื่อตีเบรกพอยต์จึงไม่จำเป็นต้องมีสายพิเศษ แต่จะง่ายกว่าที่จะเห็นคนในพื้นที่ที่มีบรรทัดพิเศษเพราะมันไม่จำเป็นต้องเพิ่มการแสดงออกใด ๆ เพิ่มเติมในการดีบักเกอร์ ดังนั้นเป็นเรื่องของการตั้งค่าส่วนตัว
Jon Raynor

3
@JonRaynor สำหรับค่าส่งคืนวางเบรกพอยต์บนวงเล็บเหลี่ยมปิดของฟังก์ชัน มันจับค่าที่ส่งคืนแม้ในฟังก์ชั่นที่มีผลตอบแทนหลาย
Baldrickk

16

บ่อยครั้งที่การแนะนำตัวแปรเพียงเพื่อตั้งชื่อผลลัพธ์บางอย่างมีประโยชน์มากเมื่อมันทำให้การจัดทำเอกสารด้วยตนเองมีรหัสมากขึ้น ในกรณีนี้ไม่ใช่ปัจจัยเพราะชื่อตัวแปรคล้ายกับชื่อเมธอด

โปรดทราบว่าวิธีการหนึ่งบรรทัดไม่มีค่าโดยธรรมชาติ หากการเปลี่ยนแปลงแนะนำบรรทัดเพิ่มเติม แต่ทำให้รหัสชัดเจนขึ้นนั่นเป็นการเปลี่ยนแปลงที่ดี

แต่โดยทั่วไปการตัดสินใจเหล่านี้ขึ้นอยู่กับความชอบส่วนบุคคลของคุณเป็นอย่างมาก เช่นฉันพบว่าทั้งสองวิธีสับสนเนื่องจากตัวดำเนินการแบบมีเงื่อนไขกำลังถูกใช้โดยไม่จำเป็น ฉันต้องการคำสั่ง if แต่ในทีมของคุณคุณอาจเห็นด้วยกับการประชุมที่แตกต่างกัน จากนั้นทำตามที่อนุสัญญาของคุณแนะนำ หากการประชุมเงียบในกรณีเช่นนี้ให้สังเกตว่านี่เป็นการเปลี่ยนแปลงเล็กน้อยมากที่ไม่สำคัญในระยะยาว หากรูปแบบนี้เกิดขึ้นซ้ำ ๆ อาจเริ่มต้นการอภิปรายว่าคุณในฐานะทีมต้องการจัดการกับกรณีเหล่านี้อย่างไร แต่นั่นเป็นการแยกเส้นขนระหว่าง "รหัสที่ดี" และ "อาจเป็นรหัสที่ดีขึ้นเล็กน้อย"


1
"ฉันพบว่าทั้งสองวิธีสับสนเนื่องจากตัวดำเนินการตามเงื่อนไขกำลังถูกใช้โดยไม่จำเป็น" - มันไม่ใช่ตัวอย่างในโลกแห่งความจริงฉันเพิ่งจะต้องทำอะไรบางอย่างขึ้นมาอย่างรวดเร็ว เป็นที่ยอมรับว่านี่อาจไม่ใช่ตัวอย่างที่ดีที่สุด
Paul Kertscher

4
+1 สำหรับการบอกว่านี่เป็นความแตกต่าง "ภายใต้เรดาร์" ที่ (สิ่งอื่นเท่ากัน) มันไม่คุ้มค่าที่จะต้องใส่ใจ
TripeHound

3
@Mindwin เมื่อฉันใช้ผู้ประกอบการที่สามฉันมักจะแยกออกเป็นหลายบรรทัดเพื่อให้ชัดเจนว่าเป็นกรณีจริงและอะไรเป็นกรณีเท็จ
Arturo Torres Sánchez

2
@ ArturoTorresSánchezฉันก็ทำเช่นนั้น แต่แทนที่จะเป็น a ?และ a :ฉันใช้if() {และ} else {- - - - \\ :)
Mindwin

3
@Mindwin แต่ฉันไม่สามารถทำได้เมื่อฉันอยู่ในช่วงกลางของการแสดงออก (เช่น initializer วัตถุ)
Arturo Torres Sánchez

2

ในการตอบคำถามของคุณ:

คำถามของฉันคือถ้ามันยังคงเป็นจุดที่ถูกต้องในการเขียนรหัสที่ชัดเจนน้อยลงเพียงเพื่อให้การดีบักการเหลือบง่ายขึ้น?

ใช่. ในความเป็นจริงส่วนหนึ่งของคำสั่งก่อนหน้านี้ดูเหมือนว่าฉัน (ไม่มีความผิด) จะน้อยสายตาสั้น (ดูตัวหนาด้านล่าง) " ข้อโต้แย้งใด ๆ ก็คือการที่อดีตตัวแปรจะง่ายต่อการแก้ปัญหา - ซึ่งค่อนข้างบุญเล็กตั้งแต่ VisualStudio ช่วยให้เราสามารถตรวจสอบคำแถลงรายละเอียดอย่างละเอียดได้เมื่อการดำเนินการหยุดลงเนื่องจากจุดพัก "

การทำให้การดีบักง่ายขึ้น (เกือบ) ไม่เคยเป็น " ข้อดีเล็กน้อย " เพราะโดยประมาณ 50% ของเวลาโปรแกรมเมอร์ใช้การดีบัก ( ซอฟต์แวร์ที่สามารถดีบักได้ )

มีข้อโต้แย้งเพิ่มเติมสำหรับชุดตัวเลือกที่มีการคำนวณแยกและใบแจ้งยอดคืนสินค้าหรือไม่

ใช่. นักพัฒนาบางคนอาจโต้แย้งว่าการคำนวณแบบแยกอ่านง่าย แน่นอนว่านี่จะช่วยในการดีบัก แต่ยังช่วยเมื่อมีคนพยายามถอดรหัสกฎเกณฑ์ทางธุรกิจที่รหัสของคุณอาจใช้หรือใช้งาน

หมายเหตุ: กฎทางธุรกิจอาจให้บริการที่ดีกว่าในฐานข้อมูลเนื่องจากสามารถเปลี่ยนแปลงได้บ่อย อย่างไรก็ตามการเข้ารหัสที่ชัดเจนในพื้นที่นี้ยังคงเป็นสิ่งสำคัญยิ่ง ( วิธีสร้างเครื่องมือสร้างกฎธุรกิจ )


1

ฉันจะไปต่อไป:

private string GetFormattedValue()
{
    if (format != null) {
        formattedString = string.Format(format, value);
    } else {
        formattedString = value.ToString()
    }
    return formattedString;
}

ทำไม?

การใช้ตัวดำเนินการที่ประกอบไปด้วยตรรกะที่ซับซ้อนมากขึ้นจะไม่สามารถอ่านได้ดังนั้นคุณจึงใช้สไตล์เช่นด้านบนสำหรับคำสั่งที่ซับซ้อนมากขึ้น ด้วยการใช้สไตล์นี้อยู่เสมอรหัสของคุณจะสอดคล้องกันและง่ายขึ้นสำหรับมนุษย์ในการแยกวิเคราะห์ นอกจากนี้โดยการแนะนำความสอดคล้องแบบนี้ (และการใช้รหัส lints และการทดสอบอื่น ๆ ) คุณสามารถหลีกเลี่ยงgoto failข้อผิดพลาดประเภท

ข้อดีอีกอย่างคือรายงานความครอบคลุมรหัสของคุณจะแจ้งให้คุณทราบหากคุณลืมที่จะรวมการทดสอบสำหรับformatไม่เป็นโมฆะ นี่จะไม่เป็นกรณีสำหรับผู้ประกอบการที่สาม


ทางเลือกที่ฉันต้องการ - หากคุณอยู่ใน "ได้รับผลตอบแทนเร็วที่สุดเท่าที่จะเป็นไปได้" และไม่เทียบกับผลตอบแทนหลายวิธี:

private string GetFormattedValue()
{
    if (format != null) {
        return string.Format(format, value);
    }

    return value.ToString();
}

ดังนั้นคุณสามารถดูผลตอบแทนล่าสุดเพื่อดูว่าค่าเริ่มต้นคืออะไร

เป็นสิ่งสำคัญที่จะต้องสอดคล้องกัน - และให้วิธีการทั้งหมดของคุณเป็นไปตามข้อตกลงหนึ่งข้อหรืออย่างอื่น


1
ตัวอย่างแรกดูเหมือนจะเป็นการปฏิบัติที่ไม่ดีเพราะvalue.ToString()ถูกเรียกโดยไม่จำเป็นเมื่อรูปแบบไม่เป็นโมฆะ ในกรณีทั่วไปซึ่งอาจรวมถึงการคำนวณที่ไม่สำคัญและอาจใช้เวลานานกว่าเวอร์ชันรวมถึงสตริงรูปแบบ ลองพิจารณาตัวอย่างเช่น a valueที่เก็บ PI เป็นทศนิยมหนึ่งล้านตำแหน่งและสตริงรูปแบบที่ร้องขอเฉพาะตัวเลขสองสามตัวแรกเท่านั้น
Steve

1
เหตุใดจึงไม่private string GetFormattedValue() => string.Format(format ?? "{0}", value); ส่งผลกระทบเหมือนกันและใช้การทดสอบหน่วยเพื่อให้แน่ใจว่าถูกต้องแทนที่จะใช้โปรแกรมดีบั๊ก
Berin Loritsch

1
ในขณะที่ฉันเห็นว่าส่วนที่สามสามารถชัดเจนน้อยกว่า null terminator สามารถทำให้สิ่งต่างชัดเจนยิ่งขึ้น อย่างน้อยในกรณีนี้
Berin Loritsch

1
เรียนไดอารี่วันนี้ฉันได้อ่านว่าการเขียนรหัสที่ชัดเจนและรัดกุมโดยใช้กระบวนทัศน์ที่รู้จักกันดี (ที่มีอยู่ประมาณ 40 ปี) สำนวนและโอเปอเรเตอร์คือการอ้างอิงการอ้างสองครั้ง แห้งและไม่ได้ใช้โอเปอเรเตอร์สำนวนและกระบวนทัศน์ดังกล่าวในขณะที่พยายามหลีกเลี่ยงสิ่งที่อาจดูเหมือนเป็นความลับเฉพาะกับเด็กอายุห้าขวบที่ไม่มีพื้นฐานการเขียนโปรแกรมมาก่อนแต่ชัดเจนกว่า นรกฉันต้องแก่แล้วจริง ๆ ไดอารี่ที่รักของฉัน ... ฉันควรจะได้เรียนรู้โกเมื่อฉันมีโอกาส
vaxquis

1
"การใช้ผู้ประกอบการที่สามเพื่อตรรกะที่ซับซ้อนมากขึ้นจะไม่สามารถอ่านได้" ในขณะที่มันเป็นจริง (และฉันได้เห็นผู้คนที่มีตรรกะที่ซับซ้อนเกินไป) สิ่งนี้ไม่เป็นความจริงสำหรับรหัสของ OP และยังไม่ใช่สิ่งที่เฉพาะเจาะจง สิ่งเดียวที่ฉันสามารถพูดได้อย่างมั่นใจคือสายยาวเกินไป gist.github.com/milleniumbug/cf9b62cac32a07899378feef6c06c776เป็นวิธีที่ฉันจะฟอร์แมตใหม่
milleniumbug

1

ฉันไม่คิดว่าเทคนิคดังกล่าวสามารถพิสูจน์ได้โดยความจำเป็นในการตรวจแก้จุดบกพร่อง ฉันได้พบกับวิธีการนี้ด้วยตัวเองเป็นพันครั้งและเป็นครั้งคราวที่ฉันทำเช่นนี้อยู่เสมอ แต่ฉันจำได้เสมอว่ามาร์ตินฟาวเลอร์พูดเกี่ยวกับการแก้ไขจุดบกพร่อง :

ผู้คนดูถูกดูแคลนเวลาที่ใช้ในการดีบัก พวกเขาดูถูกดูแคลนว่าพวกเขาสามารถใช้เวลาไล่ตามข้อบกพร่องนานเท่าใด ด้วยการทดสอบฉันรู้ทันทีเมื่อฉันเพิ่มข้อผิดพลาด ที่ให้ฉันแก้ไขข้อผิดพลาดทันทีก่อนที่จะสามารถรวบรวมข้อมูลและซ่อน มีบางสิ่งที่น่าผิดหวังหรือเสียเวลามากกว่าการดีบั๊ก จะเร็วกว่านี้หรือไม่ถ้าเราไม่ได้สร้างบั๊กตั้งแต่แรก


Martin Fowler เป็นคนฉลาดและฉันสนุกกับการอ่านมุมมอง (และของคุณ) ของเขา ในขณะที่ฉันเชื่อมั่นว่าการทดสอบเป็นสิ่งจำเป็นและควรใช้เวลามากขึ้นในความพยายามนั้นความจริงที่ว่าเราทุกคนเป็นมนุษย์ที่เข้าใจผิดได้ชี้ให้เห็นว่าไม่มีการทดสอบจำนวนมากที่จะกำจัดข้อบกพร่องทั้งหมด ดังนั้นการดีบักจะเป็นส่วนหนึ่งของการพัฒนาโปรแกรมและกระบวนการสนับสนุนเสมอ
tale852150

1

ฉันคิดว่าบางคนกำลังติดใจกับปัญหาที่สัมผัสกับคำถามเช่นผู้ประกอบการที่สาม ใช่ผู้คนจำนวนมากเกลียดชังมันดังนั้นอาจเป็นการดีถ้าคุณจะนำขึ้นมาใช้

เกี่ยวกับการมุ่งเน้นคำถามของคุณให้ย้ายข้อความที่ส่งคืนเพื่ออ้างอิงโดยตัวแปร ...

คำถามนี้ทำให้สมมติฐานที่ 2 ที่ฉันไม่เห็นด้วยกับ:

  1. ตัวแปรที่สองนั้นชัดเจนกว่าหรืออ่านง่ายกว่า (ฉันบอกว่าตรงกันข้ามนั้นเป็นจริง) และ

  2. ที่ทุกคนใช้ Visual Studio ฉันใช้ Visual Studio หลายครั้งและสามารถใช้งานได้ดี แต่ฉันมักจะใช้อย่างอื่น สภาพแวดล้อมการพัฒนาที่บังคับใช้ IDE เฉพาะนั้นเป็นสิ่งที่ฉันสงสัย

การแยกบางสิ่งออกเป็นตัวแปรที่ตั้งชื่อไม่ค่อยทำให้อะไรที่อ่านยากขึ้น ลักษณะเฉพาะที่บางคนทำก็อาจทำให้เกิดปัญหาได้เช่นถ้าเอกสารที่มีการทับซ้อนของตนเองvar thisVariableIsTheFormattedResultAndWillBeTheReturnValue = ...นั้นชัดเจนว่าเป็นสิ่งที่ไม่ดี แต่เป็นปัญหาแยกต่างหาก var formattedText = ...ไม่เป็นไร

ในกรณีเฉพาะนี้และหลาย ๆ กรณีเนื่องจากเรากำลังพูดถึง 1-liners ตัวแปรจะไม่บอกคุณมากนักว่าชื่อฟังก์ชั่นไม่ได้บอกคุณ ดังนั้นตัวแปรจึงไม่เพิ่มขึ้นมาก อาร์กิวเมนต์การดีบักอาจยังคงมีอยู่ แต่ในกรณีนี้ฉันไม่เห็นสิ่งใดที่น่าจะเป็นจุดสนใจของคุณเมื่อทำการดีบักและมันสามารถเปลี่ยนได้อย่างง่ายดายในภายหลังถ้าใครบางคนต้องการรูปแบบนั้นสำหรับการดีบักหรืออย่างอื่น

โดยทั่วไปแล้วคุณได้ขอกฎทั่วไป (ตัวอย่างของคุณเป็นเพียงแค่ตัวอย่างของแบบฟอร์มทั่วไป) จุดทั้งหมดที่ทำเพื่อสนับสนุนตัวแปร 1 (2 ซับ) นั้นถูกต้อง เหล่านี้เป็นแนวทางที่ดีที่จะมี แต่แนวทางจะต้องมีความยืดหยุ่น ตัวอย่างเช่นโครงการที่ฉันทำงานอยู่ตอนนี้มีความยาวสูงสุด 80 ตัวอักษรต่อบรรทัดดังนั้นฉันจึงแยกหลายบรรทัด แต่ฉันมักจะพบบรรทัดที่ 81-85 ตัวอักษรซึ่งน่าแปลกใจที่จะแยกหรือลดความสามารถในการอ่านและฉันทิ้งมันไว้ ขีด จำกัด.

เนื่องจากไม่น่าจะเพิ่มมูลค่าฉันจะไม่ทำ 2 บรรทัดสำหรับตัวอย่างที่ระบุ ฉันจะทำตัวแปร 2 (1 ซับ) เพราะคะแนนไม่แข็งแรงพอที่จะทำอย่างอื่นในกรณีนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.