วิธีการลดจำนวนของข้อบกพร่องเมื่อมีการเข้ารหัส?


30

ไม่มีใครสมบูรณ์แบบและไม่ว่าเราจะทำอะไรเราจะผลิตรหัสที่มีข้อบกพร่องอยู่เป็นครั้งคราว วิธีการ / เทคนิคในการลดจำนวนข้อบกพร่องที่คุณสร้างขึ้นมีอะไรบ้างทั้งในการเขียนซอฟต์แวร์ใหม่และการเปลี่ยน / การบำรุงรักษาโค้ดที่มีอยู่


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

คำตอบ:


58

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

ใช้ไลบรารีที่มีอยู่ วิธีที่ง่ายที่สุดในการไม่มีบักที่เขียนรูทีนยูทิลิตีคือการไม่เขียน

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

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

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

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

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


x2 - สิ่งที่ไรอันพูด
JBRWilkinson

2
นอกจากนี้ภาษาส่วนใหญ่สามารถเลือกมากหรือน้อย คุณต้องการให้มันพิถีพิถันมากที่สุด

1
"เรียนรู้เทคนิคที่เป็นทางการบางอย่างสำหรับสิ่งที่ซับซ้อน" ... เช่น?
Dan Rosenstark

1
@Yar: ฉันคาดหวังบางสิ่งบางอย่างเช่นระบบอธิบายไว้ในหนังสือเล่มนี้: amazon.com/Verification-Sequential-Concurrent-Programs-Computer/ … ; แม้ว่าฉันจะต้องบอกว่าหนังสือเล่มใดเล่มหนึ่งแห้งและหมองคล้ำมากดังนั้นอาจมีหนังสือที่ดีกว่านั้นออกไป (แต่มันเป็นหนังสือเล่มเดียวที่ฉันอ่าน)
Joeri Sebrechts

30

การทดสอบหน่วยช่วยให้คุณลดจำนวนข้อบกพร่องที่ปรากฏขึ้นเป็นครั้งที่สอง หากคุณพบข้อบกพร่องในรหัสของคุณการเขียนการทดสอบหน่วยจะทำให้แน่ใจว่าจะไม่กลับมาในภายหลัง (ยิ่งกว่านั้นการคิดถึงทุกกรณีและการเขียนการทดสอบหลายพันหน่วยล่วงหน้าเป็นเรื่องยากที่จะทำในบางครั้ง)


3
"การคิดถึงเคสทั้งหมดที่อยู่ข้างหน้า" นำไปสู่อินเทอร์เฟซที่สะอาดและถูกต้องซึ่งเป็นสิ่งที่ดี การทดสอบหน่วยเป็นเรื่องยากที่จะเขียนหากคุณทำการดัดแปลงให้เป็นรหัสที่ไม่ได้ออกแบบมาเพื่อการทดสอบ
Mike Seymour

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

4
"การทดสอบแสดงให้เห็นว่าไม่มีแมลงอยู่" - E. Dijkstra การทดสอบอัตโนมัติเป็นวิธีที่มีประโยชน์มากในการรักษาและเพิ่มคุณภาพของซอฟต์แวร์
limist

9

+1 ในความคิดเห็นการทดสอบทั้งหน่วย

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

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


+1 สำหรับความคิดเห็นการวิเคราะห์แบบคงที่ มันเป็นสิ่งล้ำค่าที่จะได้รับข้อมูลทั้งหมดที่ฟรี :)
มอร์เทนเซ่น

9

นอกจากสิ่งที่ถูกกล่าวถึง:

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

อีกหลายสิ่งที่ฉันลืมได้ในขณะนี้ แต่คนอื่น ๆ จะคิดถึงพวกเขาอย่างแน่นอน :)


7
และถ้าคุณแน่ใจว่าเงื่อนไข X จะไม่เกิดขึ้น ... ใช้การยืนยันเพื่อให้แน่ใจว่าเมื่อเงื่อนไข X เกิดขึ้นคุณจะรู้เกี่ยวกับมัน (ผ่านข้อยกเว้นหรือการบันทึกหรืออะไรก็ตาม)
Frank Shearar

@MetalMikester: การทดสอบหน่วยดี แต่ด้วยภาษาระดับสูงและห้องสมุดที่ดีส่วนใหญ่ของข้อบกพร่องที่ยากต้องใช้การรวมและการทดสอบการถดถอยเพื่อตอกตะปู
เวกเตอร์

9

ฉันได้พัฒนารูปแบบการเขียนโปรแกรมที่ใช้งานได้ดีแม้ว่าภาษาหลักของฉันคือ C ++ และ Python ฉันพบว่าถ้าฉันส่งบริบททั้งหมดไปยังฟังก์ชัน (หรือวิธีการ) ที่ฟังก์ชันนั้นต้องทำงานและส่งคืนข้อมูลที่มีความหมายที่ฉันกำลังมองหารหัสของฉันก็แข็งแกร่งขึ้นมาก

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

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

ไปคิดทุกสิ่งเหล่านี้ยังมีผลกระทบในเชิงบวกต่อประสิทธิภาพเช่นกัน ชนะ!


จากประสบการณ์ของฉันมันอาจกลายเป็นเรื่องน่าเบื่ออย่างรวดเร็วที่จะต้องผ่านทุกสถานะของการโทรทุกครั้งหากวิธีการมีขนาดเล็กเท่าที่ควร ปัญหานี้สามารถแก้ไขได้โดยใช้คลาสที่ไม่เปลี่ยนรูปขนาดเล็กจำนวนมากพร้อมอายุการใช้งานวัตถุสั้น ด้วยวิธีนี้คุณสามารถจัดเก็บสถานะชั่วคราวเป็นเขตข้อมูลและทิ้งวัตถุเมื่อคุณไม่ต้องการสถานะอีกต่อไป :-)
Jørgen Fogh

ข้อพิจารณาอีกประการหนึ่งสำหรับกรณีนี้ว่ามันน่าเบื่อก็คือบางทีคุณอาจพยายามที่จะผ่านรอบรัฐมากเกินไป :)
dash-tom-bang

ในหลายกรณีที่เป็นจริง แต่มักจะไม่ ภายในบางโดเมนคุณจำเป็นต้องเข้าถึงรัฐจำนวนมากแม้ว่าคุณจะมีสถานะที่ไม่แน่นอนจำนวนมาก ขณะนี้ฉันกำลังทำงานกับเครื่องกำเนิดรหัสที่ฉันต้องการเข้าถึงตารางสัญลักษณ์ต่างๆ ฉันไม่ต้องการส่งผ่านไปยังแต่ละวิธี
Jørgen Fogh

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

ฉันจะเขียนโพสต์ขนาดใหญ่ที่สรุปว่า "เขียนได้น้อยลงและทำได้มากกว่า" (ฉันรู้และใช้เครื่องมือที่มีให้สำหรับคุณ) ฉันจะ +1 มันแทน
Kaz Dragon

1
แต่ระวังอย่าให้รหัสแฟนซีเมื่อพยายามที่จะบรรลุรหัสน้อย
gablin

1
@ แกบลิน: จินตนาการอยู่ในสายตาของคนดูหลายประการ ฉันสามารถเขียนและอ่านรหัสได้ในวันนี้ว่าฉันจะงงงวยเมื่อ 4 ปีก่อน Haskellวันนี้เป็นสิ่งที่แปลกสำหรับฉัน :)
Paul Nathan

8

คำตอบทางเทคนิคเล็กน้อยน้อย: อย่าโปรแกรมเมื่อคุณเหนื่อย (9h / วันก็เพียงพอ) เมาหรือ 'อบ' เมื่อฉันเหนื่อยฉันไม่มีความอดทนที่จะเขียนรหัสสะอาด


2
โดยปกติโปรแกรมเมอร์ส่วนใหญ่จะใช้เวลาหลายปีกว่าจะรู้เรื่องนี้ มันเป็นจุดสำคัญ
Jeff Davis


5

คำตอบที่ดีเกี่ยวกับการทดสอบหน่วยและเครื่องมือที่นี่ สิ่งเดียวที่ฉันสามารถเพิ่มให้พวกเขาคือ:

เกี่ยวข้องกับผู้ทดสอบของคุณให้เร็วที่สุดเท่าที่จะทำได้

หากคุณมีทีมทดสอบอย่าตกหลุมพรางในการปฏิบัติต่อพวกเขาในฐานะผู้รักษาประตูสำหรับคุณภาพรหัสของคุณและตรวจจับข้อบกพร่องของคุณ ให้ทำงานร่วมกับพวกเขาและให้เร็วที่สุดเท่าที่จะเป็นไปได้ (ในโครงการที่มีความคล่องตัวนี้จะมาจากจุดเริ่มต้นของโครงการ แต่เราสามารถหาวิธีที่จะเข้ามามีส่วนร่วมได้เร็วขึ้น

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

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


4

เครื่องมือวิเคราะห์แบบคงที่

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

PS: จำไว้ว่าให้ทำการค้นคว้าเสมอว่าทำไมเครื่องมือถึงบอกสิ่งที่ไม่ดี อย่าเจ็บที่จะเรียนรู้ (และไม่ใช่ทุกอย่างที่ถูกต้องในทุกสถานการณ์)


3

การตรวจสอบรหัสหรือรูปแบบอื่น ๆ ของการตรวจสอบโดยเพื่อนเช่นการเขียนโปรแกรมคู่

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

รีวิว Peer in Software โดย Karl Wiegersเป็นหนังสือที่ยอดเยี่ยมในเรื่องนี้


2

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

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


2

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

ทำความรู้จักกับธุรกิจที่คุณสนับสนุนคุณมักจะเห็นสิ่งต่าง ๆ ตามข้อกำหนดที่ขาดหายไปหรือต้องการคำอธิบายเพิ่มเติม รู้ว่าถ้าคุณทำงาน Y ตามที่ระบุไว้มันจะทำลายฟีเจอร์ Z ที่มีอยู่

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


1

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

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


1

ฉันทำตามแบบฝึกหัดของ Test-Code-Test แทน Code-test-code-test สิ่งนี้ช่วยให้ฉันคิดถึงกรณีการใช้งานและจัดวางตรรกะอย่างเหมาะสม


1

ใช้เครื่องมือตรวจสอบรหัสเช่นReSharperหรือ IDEs เช่นIntelliJ IDEAที่เตือนเกี่ยวกับข้อผิดพลาดในการคัดลอกและวางและอื่น ๆ เช่นชี้ให้เห็นตัวแปรที่ "เขียนถึง แต่ไม่เคยอ่าน" ช่วยฉันได้เยอะ


1

น่าประหลาดใจที่ประเด็นสำคัญสามข้อต่อไปนี้ยังไม่ได้กล่าวถึง:

  • ใช้การยืนยันอย่างอิสระ คำถามที่คุณควรถามตัวเองอยู่เสมอไม่ใช่ "ฉันควรยืนยันเรื่องนี้หรือไม่?" แต่ "มีอะไรฉันลืมยืนยัน?"

  • เลือกไม่เปลี่ยนรูป (ใช้ขั้นตอนสุดท้าย / แบบอิสระอย่างอิสระ) สถานะที่ไม่แน่นอนที่คุณมีน้อยกว่าสิ่งที่น้อยกว่าอาจผิดไป

  • อย่าปรับให้เหมาะสมก่อนเวลาอันควร โปรแกรมเมอร์จำนวนมากได้รับการติดตามโดยมีข้อกังวลเกี่ยวกับประสิทธิภาพทำให้พวกเขาสับสนกับโค้ดโดยไม่จำเป็นและทำให้การออกแบบแย่ลงโดยไม่ทราบล่วงหน้าว่าประสิทธิภาพนั้นจะเป็นปัญหาหรือไม่ ขั้นแรกให้สร้างผลิตภัณฑ์ซอฟต์แวร์ของคุณตามแนวทางวิชาการโดยไม่สนใจประสิทธิภาพ จากนั้นดูว่ามันทำงานได้ไม่ดีหรือไม่ (อาจจะไม่ได้) หากมีปัญหาด้านประสิทธิภาพให้ไปหาหนึ่งหรือสองแห่งที่คุณสามารถให้การปรับอัลกอริธึมที่ดีและเป็นทางการซึ่งจะทำให้ผลิตภัณฑ์ของคุณตรงตามข้อกำหนดด้านประสิทธิภาพแทนที่จะปรับแต่งและแฮ็ครหัสฐานทั้งหมดของคุณ บีบวงจรนาฬิกาที่นี่และที่นั่น

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