วิศวกรรมซอฟต์แวร์

ถาม - ตอบสำหรับมืออาชีพนักวิชาการและนักเรียนที่ทำงานในวงจรการพัฒนาระบบ

4
วิธีที่ดีที่สุดในการเขียนวิธี“ ลอง” ใน C # 7 คืออะไร
ฉันกำลังเขียนการใช้ Queue ประเภทที่มีTryDequeueวิธีการที่ใช้รูปแบบคล้ายกับTryParseวิธีการ. NET ต่าง ๆซึ่งฉันส่งคืนค่าบูลีนหากการดำเนินการสำเร็จและใช้outพารามิเตอร์เพื่อส่งคืนค่าที่ถูกตัดจริง public bool TryDequeue(out Message message) => _innerQueue.TryDequeue(out message); ตอนนี้ฉันชอบหลีกเลี่ยงoutparams ทุกครั้งที่ทำได้ C # 7 ทำให้เรามีตัวแปรต่าง ๆ เพื่อให้การทำงานกับมันง่ายขึ้น แต่ฉันยังคงพิจารณาถึงความชั่วร้ายที่จำเป็นมากกว่าเครื่องมือที่มีประโยชน์ พฤติกรรมที่ฉันต้องการจากวิธีนี้มีดังนี้: หากมีรายการที่จะ dequeue คืนมัน หากไม่มีรายการที่จะถอน (คิวว่างเปล่าให้ผู้โทรมีข้อมูลเพียงพอที่จะดำเนินการอย่างเหมาะสม อย่าเพิ่งส่งคืนรายการที่ไม่มีค่าหากไม่มีรายการที่เหลืออยู่ อย่าโยนข้อยกเว้นหากพยายาม dequeue จากคิวที่ว่างเปล่า ตอนนี้ผู้เรียกใช้เมธอดนี้มักจะใช้รูปแบบดังต่อไปนี้ (โดยใช้ไวยากรณ์ตัวแปร C # 7 out): if (myMessageQueue.TryDequeue(out Message dequeued)) MyMessagingClass.SendMessage(dequeued) else Console.WriteLine("No messages!"); // do other …
21 c# 

3
เป็นการออกแบบปกติหรือไม่ที่จะแยกแบ็กเอนด์และส่วนหน้าเว็บแอปพลิเคชันอย่างสมบูรณ์และอนุญาตให้พวกเขาสื่อสารกับ (JSON) REST API ได้หรือไม่?
ฉันกำลังสร้างเว็บแอปพลิเคชันธุรกิจใหม่และฉันต้องการบรรลุ: ใช้เทคโนโลยีที่ดีที่สุดจากอาณาจักรที่เกี่ยวข้อง ฉันต้องการกรอบแบ็กเอนด์ที่เชื่อถือได้ด้วย ORM ที่มั่นคง และฉันต้องการเฟรมเวิร์ก SPA (แอปพลิเคชันหน้าเดียว) ที่ทันสมัยที่สุดด้วยการใช้คุณสมบัติ HTML และ Javascript ล่าสุดสำหรับแอปพลิเคชันส่วนหน้า เปิดเผยเอนทิตีแบ็กเอนด์และบริการธุรกิจสำหรับการใช้งานจากแอพพลิเคชั่นประเภทต่าง ๆ เช่นเว็บแอพพลิเคชั่นมือถือ (Android) และประเภทอื่น ๆ (อุปกรณ์สมาร์ทเป็นต้น) ดังนั้น - เพื่อตอบสนองความต้องการทั้งสองอย่างฉันมีแนวโน้มที่จะแยกแอปพลิเคชันของฉันออกอย่างสมบูรณ์ในแอปพลิเคชันส่วนหลังและส่วนหน้าและจัดการการสื่อสารระหว่างกันโดยใช้ REST API (JSON) เสียงนี้เข้าใกล้หรือไม่? การแยกดังกล่าวไม่ใช่โซลูชันการออกแบบที่ชัดเจนเนื่องจากเทคโนโลยีเว็บแอปพลิเคชันจำนวนมากได้รวมเลเยอร์มุมมองไว้ซึ่งแอปพลิเคชันฝั่งเซิร์ฟเวอร์จะควบคุมการสร้างมุมมองมากขึ้นหรือน้อยลงและจัดการการตอบสนองจากมุมมองบางส่วน layer, Java JSF / Facelets จะบันทึกสถานะของส่วนประกอบบนเซิร์ฟเวอร์อย่างสมบูรณ์) ดังนั้น - มีเทคโนโลยีมากมายที่เสนอการมีเพศสัมพันธ์ที่แข็งแกร่งมากขึ้นและให้สัญญาว่าจะพัฒนาได้เร็วขึ้นและมีเส้นทางการเดินทางที่เป็นมาตรฐานมากขึ้น ดังนั้น - ฉันต้องระวังเมื่อเริ่มใช้เทคโนโลยีในลักษณะที่ไม่ได้ใช้กันอย่างแพร่หลาย ตามที่ฉันเข้าใจแล้วส่วนหน้าของ SPA ที่แยกจากกันอย่างสมบูรณ์มักเกิดจากความจำเป็นในการใช้ API ของบุคคลที่สาม แต่การออกแบบเสียง decoupling ดังกล่าวเมื่อทั้งสองแบ็กเอนด์และส่วนหน้าได้รับการพัฒนาโดย บริษัท หนึ่ง? …

5
ควรย้ายเงื่อนไขที่ไม่น่าสนใจไปยังส่วนเริ่มต้นของลูปหรือไม่?
ฉันได้ความคิดนี้จากคำถามนี้ใน stackoverflow.com รูปแบบต่อไปนี้เป็นเรื่องธรรมดา: final x = 10;//whatever constant value for(int i = 0; i < Math.floor(Math.sqrt(x)) + 1; i++) { //...do something } จุดที่ฉันพยายามทำคือข้อความที่มีเงื่อนไขเป็นเรื่องที่ซับซ้อนและไม่เปลี่ยนแปลง มันเป็นการดีกว่าที่จะประกาศในส่วนเริ่มต้นของลูปเช่นนี้? final x = 10;//whatever constant value for(int i = 0, j = Math.floor(Math.sqrt(x)) + 1; i < j; i++) { //...do something } ชัดเจนกว่านี้ไหม เกิดอะไรขึ้นถ้านิพจน์เงื่อนไขนั้นง่ายเช่น …

5
วิธีการแก้ไขข้อผิดพลาดในการทดสอบหลังจากการเขียนการใช้งาน
การกระทำที่ดีที่สุดใน TDD คืออะไรหากหลังจากใช้ตรรกะอย่างถูกต้องการทดสอบยังคงล้มเหลว (เพราะมีข้อผิดพลาดในการทดสอบ)? ตัวอย่างเช่นสมมติว่าคุณต้องการพัฒนาฟังก์ชั่นต่อไปนี้: int add(int a, int b) { return a + b; } สมมติว่าเราพัฒนามันในขั้นตอนต่อไปนี้: ทดสอบการเขียน (ยังไม่มีฟังก์ชั่น): // test1 Assert.assertEquals(5, add(2, 3)); ผลลัพธ์มีข้อผิดพลาดในการรวบรวม เขียนการใช้งานฟังก์ชันหลอกตา: int add(int a, int b) { return 5; } ผลลัพธ์: test1ผ่าน เพิ่มกรณีทดสอบอื่น: // test2 -- notice the wrong expected value (should be 11)! Assert.assertEquals(12, …
21 tdd  mistakes 

3
สิ่งที่ควรเป็นประเภทข้อมูลของโทเค็นที่ lexer กลับไปที่ parser ของมัน?
ตามที่ระบุไว้ในชื่อแล้วข้อมูลชนิดใดที่ lexer ส่งคืน / ให้ parser? เมื่ออ่านบทความวิเคราะห์คำศัพท์ที่ Wikipedia มีระบุว่า: ในวิทยาการคอมพิวเตอร์การวิเคราะห์คำศัพท์เป็นกระบวนการของการแปลงลำดับของตัวละคร (เช่นในโปรแกรมคอมพิวเตอร์หรือหน้าเว็บ) เป็นลำดับโทเค็น ( สตริงที่มีการระบุ "ความหมาย") อย่างไรก็ตามในความขัดแย้งที่สมบูรณ์ให้กับคำสั่งดังกล่าวเมื่อคำถามอื่นผมถามในเว็บไซต์ที่แตกต่างกัน ( รหัสการตรวจทานถ้าคุณอยากรู้) ได้รับการตอบคนตอบระบุไว้ว่า: lexer มักจะอ่านสตริงและแปลงเป็นกระแส ... ของ lexemes คำศัพท์จะต้องเป็นตัวเลขของสตรีมเท่านั้น และเขาให้ภาพนี้: nl_output => 256 output => 257 <string> => 258 ต่อมาในบทความเขากล่าวถึงFlexเล็กซ์ที่มีอยู่แล้วและกล่าวว่าการเขียน 'กฎ' กับมันจะง่ายกว่าการเขียนเล็กซ์เซอร์ด้วยมือ เขาดำเนินการให้ฉันตัวอย่างนี้: Space [ \r\n\t] QuotedString "[^"]*" %% nl_output {return 256;} output {return …
21 data-types  lexer  flex 

3
วิธีจัดการกรณีความล้มเหลวในตัวสร้างคลาส C ++
ฉันมีคลาส CPP ซึ่งตัวสร้างทำการดำเนินการบางอย่าง การดำเนินการบางอย่างอาจล้มเหลว ฉันรู้ว่าผู้สร้างไม่คืนสิ่งใด คำถามของฉันคือ มันอนุญาตให้ดำเนินการบางอย่างอื่น ๆ ที่เริ่มต้นสมาชิกในนวกรรมิก? เป็นไปได้ไหมที่จะบอกฟังก์ชั่นการโทรว่าการทำงานบางอย่างใน Constructor ล้มเหลว? ฉันจะnew ClassName()คืนค่า NULL ได้ไหมหากมีข้อผิดพลาดเกิดขึ้นในตัวสร้าง?

4
เหตุใด Git .git / objects / โฟลเดอร์จึงถูกแบ่งย่อยในหลาย ๆ โฟลเดอร์ของ SHA-prefix
Git เก็บวัตถุ (Blobs, trees) ไว้ใน.git/objects/โฟลเดอร์ แต่ละวัตถุสามารถอ้างอิงได้โดยแฮช SHA1 ที่คำนวณจากเนื้อหาของวัตถุ อย่างไรก็ตามวัตถุจะไม่ถูกเก็บไว้ใน.git/objects/โฟลเดอร์โดยตรง แต่ละวัตถุจะถูกเก็บไว้ในโฟลเดอร์ที่ขึ้นต้นด้วยคำนำหน้าของแฮช SHA1 ดังนั้นวัตถุที่มีแฮชb7e23ec29af22b0b4e41da31e868d57226121c84จะถูกเก็บไว้ที่.git/objects/b7/e23ec29af22b0b4e41da31e868d57226121c84 เหตุใด Git จึงแบ่งการจัดเก็บวัตถุด้วยวิธีนี้ ทรัพยากรที่ฉันสามารถหาเช่นหน้า internals Git ของใน Git-SCM, เท่านั้นอธิบายวิธีการที่ไม่ว่าทำไม

3
ชื่อ 'ข้อมูลจำเพาะ' ของฟังก์ชั่น / วิธีคืออะไร?
ฉันค่อนข้างแน่ใจว่ามีชื่อพิเศษสำหรับ 'ข้อมูลจำเพาะ' ของฟังก์ชัน / วิธี มันเป็นคำที่หมายถึง ต้องใช้อาร์กิวเมนต์กี่ครั้ง ลำดับของการขัดแย้ง อาร์กิวเมนต์ใดเป็นตัวเลือก มีชื่อไหม?

2
เพิ่มประสิทธิภาพ repo คอมไพล์ที่มีไฟล์ไบนารีขนาดใหญ่
โครงการของเรามีขนาดประมาณ 11GB, 10 แห่งเป็นข้อมูลไบนารี่ (.png ภาพ) ดังนั้นการดำเนินการgit diffหรือgit statusใช้เวลานานกว่าหนึ่งนาที dataโชคดีที่ไฟล์ข้อมูลทั้งหมดจะถูกแยกออกไปไว้ในโฟลเดอร์ที่มีชื่อที่ยอดเยี่ยม การมอบหมายคือ "หลีกเลี่ยงการบีบอัดการกระจายและการดำเนินการอื่น ๆ ที่มีราคาแพงในไฟล์ไบนารี" ถือว่าเป็นการแยกโครงการออกเป็นสอง repos จากนั้นdataจะเป็น repo ภายนอกที่ถูกตรวจสอบโดย repo ซอร์สโค้ดหลัก มีการตัดสินใจแล้วว่าค่าใช้จ่ายในการรักษา repos นั้นจะมากเกินไปโดยเฉพาะอย่างยิ่งสำหรับศิลปินที่ทำงานกับไฟล์ข้อมูล อย่างชัดเจนบอกคอมไพล์ไฟล์เหล่านั้นเป็นไบนารี , ไม่รวมไฟล์จาก diffsได้รับการพิจารณา แต่ผู้ที่ดูเหมือนเพียงบางส่วนเพื่อแก้คำถาม ฉันรู้สึกว่าคุณลักษณะคอมไพล์เป็นวิธีแก้ปัญหา แต่อย่างไร หรือมีสถาปัตยกรรมที่ดีกว่า repo เสาหิน?
21 git  binary 

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

6
รหัสทางวิทยาศาสตร์เป็นขอบเขตที่แตกต่างกันมากพอที่จะเพิกเฉยต่อมาตรฐานการเข้ารหัสทั่วไปหรือไม่?
เมื่อไม่นานมานี้ฉันพยายามจะปิดปากเรื่องดังต่อไปนี้ ในอีกด้านหนึ่งมีโฮสต์ของแนวทางการเข้ารหัสและมาตรฐานสำหรับสิ่งที่ถือว่าเป็น "สุขภาพ", "สะอาด", "ดีเขียน" และอื่น ๆ รหัส ดู "รหัสสะอาด" ที่ดูเหมือนจะพูดถึงกันอย่างกว้างขวางที่นี่เช่นกัน กฎตัวอย่าง: วิธียาว 7 บรรทัดและ 1 หรือ 2 ระดับของการเยื้อง รหัสที่ไม่ได้ปฏิบัติตามคาดว่าจะตายจากการบำรุงรักษาที่ไม่ดี ในทางกลับกันฉันได้ทำงานกับ OpenCV, OpenCascade, VTK และอื่น ๆ มันเป็นรหัสทางวิทยาศาสตร์ พวกเขามีวิธีการยาว 2 หน้า (sen ตัวเอง), OpenCascade มีวิธีการหรือคลาสแบ่งออกเป็น 10 ไฟล์ (ไม่มีเรื่องตลกที่นี่) VTK เป็นระเบียบในบางครั้งเช่นกัน แต่โครงการเหล่านี้ประสบความสำเร็จได้รับการดูแลและใช้อย่างกว้างขวาง! จับได้ที่ไหน เราได้รับอนุญาตให้เขียนโค้ดทางวิทยาศาสตร์คณิตศาสตร์หนัก ๆ ในแบบที่มันใช้งานได้และเราสามารถรักษามันไว้ได้หรือไม่? คุณเป็นชุดมาตรฐานแยกต่างหากสำหรับโครงการดังกล่าวหรือไม่ถ้ามี อาจเป็นคำถามที่ไร้เดียงสา แต่ฉันอยู่ในสิ่งที่ดูเหมือนจะเป็นโมฆะการเขียนโปรแกรมพยายามสร้างชุดของกฎวิธีการทำและไม่ทำสิ่งต่าง ๆ ซึ่งเป็นวิธีที่ฉันได้รับการสอนให้ทำงานที่โรงเรียนมัธยม นับตั้งแต่ที่ฉันเรียนจบฉันแทบจะไม่ได้รับการชี้นำจากสิ่งที่ฉันต้องทำโดยเฉพาะอย่างยิ่งการเขียนโปรแกรม …

3
ชื่อวิธีการที่“ บวก” และ“ ลบ” เหมาะสมหรือไม่
Java SE 8 มาพร้อมกับกลไกใหม่สำหรับวันที่แนะนำLocalDate, LocalTimeและLocalDateTimeชั้นเรียนเพื่อเป็นตัวแทนของจังหวะเวลา เพื่อจัดการกับจังหวะดังกล่าวเป็นชุดของวิธีการที่จะได้รับ: LocalDate.plusDays(...), LocalDate.minusDays(...)และอื่น ๆ ฉันคิดเสมอว่าวิธีปฏิบัติที่ดีคือการตั้งชื่อวิธีการหลังจากคำกริยาอธิบายถึงจุดประสงค์ของพวกเขาเช่นเดียวกับวิธีการที่เป็นจริงการดำเนินการที่จะดำเนินการสิ่งที่จะดำเนินการ เพียงแค่พูดถึงถ้าคุณพิจารณาการเรียนเหมือนStringBuilderเช่นชื่อวิธีการมีappend, insert, delete... นี่คือเหตุผลที่ฉันก็ไม่ได้เสียงที่เหมาะสมในการตั้งชื่อวิธีการplusDaysแทนsumDays, แทนminusDays subtractDaysฉันแค่พบว่ามันน่ารำคาญมาก? คุณคิดอย่างไร? เหตุผลเดียวที่ฉันนึกได้ก็คือวันที่นั้นเป็นวัตถุที่ไม่เปลี่ยนรูปดังนั้นโดยการโทรplusDaysคุณไม่ได้เพิ่มวันในวัตถุดั้งเดิม แต่สร้างวันใหม่ด้วยคุณสมบัติใหม่ แต่นั่นช่างลึกซึ้งมาก

2
ประเภทความกว้างของตัวแปรถูกแทนที่ด้วยประเภทคงที่ในโมเดิร์นซีหรือไม่
ฉันมาข้ามจุดที่น่าสนใจวันนี้ในการตรวจสอบมากกว่าเมื่อรหัสตรวจสอบ @Veedrac recommened ในคำตอบนี้ว่าประเภทขนาดตัวแปร (เช่นintและlong) ถูกแทนที่ด้วยประเภทขนาดคงที่เหมือนและuint64_t uint32_tการอ้างอิงจากความคิดเห็นของคำตอบนั้น: ขนาดของ int และ long (และค่าที่สามารถเก็บได้) นั้นขึ้นอยู่กับแพลตฟอร์ม ในทางตรงกันข้าม int32_t จะยาว 32 บิตเสมอ การใช้ int เพียงหมายความว่าโค้ดของคุณทำงานแตกต่างกันไปตามแพลตฟอร์มต่าง ๆ ซึ่งโดยทั่วไปไม่ใช่สิ่งที่คุณต้องการ เหตุผลที่อยู่เบื้องหลังมาตรฐานไม่ได้กำหนดชนิดที่พบจะมีการอธิบายบางส่วนที่นี่โดย @supercat C ถูกเขียนเป็นแบบพกพาข้ามสถาปัตยกรรมในทางตรงกันข้ามกับการชุมนุมซึ่งมักจะใช้สำหรับการเขียนโปรแกรมระบบในเวลา ฉันคิดว่าความตั้งใจในการออกแบบนั้น แต่เดิมนั้นแต่ละประเภทอื่น ๆ นอกเหนือจาก int เป็นสิ่งที่เล็กที่สุดที่สามารถรองรับตัวเลขขนาดต่างๆและ int นั้นเป็นขนาด "วัตถุประสงค์ทั่วไป" ที่ใช้งานได้จริงที่สุดที่สามารถจัดการ +/- 32767 สำหรับฉันฉันมักจะใช้intและไม่ได้กังวลเกี่ยวกับทางเลือก ฉันคิดเสมอว่ามันเป็นประเภทที่มีประสิทธิภาพดีที่สุดจบเรื่อง ที่เดียวที่ฉันคิดว่าความกว้างคงที่จะมีประโยชน์คือเมื่อเข้ารหัสข้อมูลสำหรับการจัดเก็บหรือถ่ายโอนผ่านเครือข่าย ฉันเคยเห็นประเภทความกว้างคงที่ในโค้ดที่เขียนโดยคนอื่นด้วย ฉันติดอยู่ในยุค 70 หรือมีเหตุผลintในการใช้งานในยุค C99 หรือไม่?

6
ควรมีวิธีการให้อภัยเมื่อมีข้อโต้แย้งที่ผ่านเข้ามาหรือไม่? [ปิด]
ปิด คำถามนี้จะต้องมีมากขึ้นมุ่งเน้น ไม่ยอมรับคำตอบในขณะนี้ ต้องการปรับปรุงคำถามนี้หรือไม่ อัปเดตคำถามเพื่อให้มุ่งเน้นที่ปัญหาเดียวโดยแก้ไขโพสต์นี้ ปิดให้บริการใน4 ปีที่แล้ว สมมติว่าเรามีวิธีการfoo(String bar)ที่ทำงานบนสตริงที่ตรงกับเกณฑ์บางอย่างเท่านั้น [a-z0-9-_./@]+ตัวอย่างเช่นมันจะต้องเป็นตัวพิมพ์เล็กต้องไม่ว่างเปล่าหรือมีเพียงช่องว่างและต้องตรงกับรูปแบบ เอกสารประกอบสำหรับวิธีการระบุเกณฑ์เหล่านี้ วิธีการที่ควรปฏิเสธการเบี่ยงเบนใด ๆ และทั้งหมดจากเกณฑ์นี้หรือวิธีการควรให้อภัยมากขึ้นเกี่ยวกับเกณฑ์บางอย่าง? ตัวอย่างเช่นถ้าวิธีการเริ่มต้นคือ public void foo(String bar) { if (bar == null) { throw new IllegalArgumentException("bar must not be null"); } if (!bar.matches(BAR_PATTERN_STRING)) { throw new IllegalArgumentException("bar must match pattern: " + BAR_PATTERN_STRING); } this.bar = bar; } …
21 java  parameters 

4
วิธีการหลีกเลี่ยงการทำซ้ำตรรกะระหว่างคลาสโดเมนและแบบสอบถาม SQL คืออะไร
ตัวอย่างด้านล่างเป็นสิ่งประดิษฐ์โดยสิ้นเชิงและจุดประสงค์เพียงอย่างเดียวคือเพื่อให้ได้จุดของฉัน สมมติว่าฉันมีตาราง SQL: CREATE TABLE rectangles ( width int, height int ); ระดับโดเมน: public class Rectangle { private int width; private int height; /* My business logic */ public int area() { return width * height; } } ตอนนี้สมมติว่าฉันมีความต้องการที่จะแสดงให้ผู้ใช้เห็นพื้นที่ทั้งหมดของรูปสี่เหลี่ยมผืนผ้าทั้งหมดในฐานข้อมูล ฉันสามารถทำได้โดยดึงแถวทั้งหมดของตารางเปลี่ยนเป็นวัตถุและวนซ้ำไปมา แต่มันดูโง่มากเพราะฉันมีรูปสี่เหลี่ยมผืนผ้ามากมายในตาราง ดังนั้นฉันทำสิ่งนี้: SELECT sum(r.width * r.height) FROM rectangles r ง่ายรวดเร็วและใช้จุดแข็งของฐานข้อมูล …

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