วัตถุประสงค์ของการสร้างเครื่องจักรเฉพาะคืออะไร?


75

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

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

แนวคิดของการมีเครื่องบิลด์แยกต่างหากเดิมคือเพื่อแยกโค้ดที่เขียนในเครื่องของฉันออกจากรหัสของนักพัฒนาอื่น ๆ และเพื่อแยกไฟล์ hijacked ใด ๆ ที่ฉันมีบนเครื่องออกจากการปรับใช้ นอกจากนี้ยังเป็นการแก้ไขข้อกังวลที่เพิ่มขึ้นที่ฉันเคยมีกับระบบจัดการไฟล์ ClearCase ของเราซึ่งมักจะปฏิเสธที่จะให้ฉันปรับใช้กิจกรรมบิลด์บางอย่างยกเว้นว่าฉันได้รวมกิจกรรมอื่นที่ 'พึ่งพา' ด้วย

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

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


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


13
WTF ที่แท้จริงคือ Clearcase ซึ่งแย่กว่าตัวเลือกโอเพนซอร์สสมัยใหม่ทั้งหมด โครงการนี้ภาษาใดและมีขนาดใหญ่ / ซับซ้อนเพียงใด
pjc50

7
คุณใช้เครื่องมือ? Git / SVN และ Jenkins / Team City / Octopus / TFS เป็นต้น หรือคุณเพียงแค่ลงชื่อเข้าใช้คอมพิวเตอร์เครื่องอื่นโหลด Visual Studio หรือคุณมี ... คัดลอกโครงการโหลดรวบรวม ... คุณใช้เครื่องมือระดับมืออาชีพหรือทำด้วยตนเองหรือไม่
WernerCD

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

คำตอบ:


138

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

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

โดยทั่วไปผู้ใช้หลาย ๆ คนหรือทีมงาน Build สามารถเข้าถึงเซิร์ฟเวอร์พร้อมกันได้โดยใช้ web gui ที่ทำงานในเบราว์เซอร์

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


3
จริงๆแล้วฉันไม่ได้แตะ c ++ มาตั้งแต่เรียนมหาวิทยาลัย แต่ฉันเข้าใจถึงประโยชน์ได้ แม้ว่าในกรณีนี้ฉันคิดว่าสิ่งที่เรากำลังทำจริงอาจถูกลบออกไปไกลจากจุดประสงค์ที่ตั้งใจไว้
Zibbobz

21
สำหรับบางภาษา (โดยเฉพาะอย่างยิ่ง C ++) การมีกล่องเฉพาะที่มีพลังการประมวลผลมากขึ้นก็มีประโยชน์เช่นกันเนื่องจากมันเป็นการรวบรวมที่ค่อนข้างช้า
enderland

31
การรวมอย่างต่อเนื่องหมายถึงมากกว่าแค่การสร้างเซิร์ฟเวอร์ - มันยังหมายถึงทุกคนรวมการเปลี่ยนแปลงซึ่งกันและกันบ่อยที่สุดเท่าที่จะทำได้เพื่อหลีกเลี่ยงปัญหาการรวม "บิ๊กแบง" มิฉะนั้นจุดบน
Rob Crawford

ในขณะที่ฉันชอบพลังที่มีตัวอย่างให้กับจุดที่ทำที่นี่ฉันยังคงคิดว่าย่อหน้าสุดท้ายไม่จำเป็นทั้งหมดในคำตอบนี้
Pierre Arlaud

3
"เครื่องจักรสร้างโดยเฉพาะให้ประโยชน์จากการไม่ปิดกั้นการทำงานของนักพัฒนาและปรับใช้จากเครื่องรวมศูนย์" ไม่เป็นความจริงทั้งหมด ผู้ถามชี้ให้เห็นว่ามันง่ายมากที่จะมีสภาพแวดล้อมที่ไม่สะอาดในเครื่องของนักพัฒนา ไลบรารีที่รวมอยู่และตัวแปรสภาพแวดล้อมอื่น ๆ ทั้งหมดสามารถเปลี่ยนผลลัพธ์การสร้างได้ เครื่องจักรเฉพาะควรมีสภาพแวดล้อมที่มีเอกสารที่ดีเพื่อให้ง่ายต่อการสร้างนันทนาการ
TafT

107

นอกเหนือจากคำตอบของ Traubenfuchs แล้วคุณยังได้บอกใบ้อีกเหตุผลหนึ่งสำหรับการสร้างเครื่องจักรในคำถามของคุณ

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

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


37
+ 1 จำนวนครั้งที่บางสิ่งบางอย่างทำงานได้บนเครื่องจักรของนักพัฒนา แต่ไม่ใช่ส่วนที่เหลือของทีมของเขา ...
user2259716

45
นี้. หลักวัตถุประสงค์ของการสร้างเครื่องอื่นที่จะมีการทำซ้ำสร้าง ; ยวดโดยการกำจัดสิ่งที่ไม่มุ่งมั่นตัวแปรสภาพแวดล้อมที่แตกต่างกัน ฯลฯ ... จากสมการ
Matthieu M.

9
ขยายที่: ใช้อิมเมจคอนเทนเนอร์ใหม่ที่สะอาดซึ่งคุณเริ่มสร้างแต่ละบิลด์ จากนั้นให้สคริปต์การบูตติดตั้งระบบ ที่รับประกันการสร้างซ้ำอย่างแท้จริง
Matthias Kuhn

9
@MatthiasKuhn: แท้จริง (ไบต์ต่อไบต์) การสร้างซ้ำต้องมีอีกมาก cf: reproducible-builds.org wiki.debian.org/ReproducibleBuilds
ninjalj

1
นอกจากนี้เนื่องจากผลิตภัณฑ์รุ่น Linux สร้างและผ่านการทดสอบบนเดสก์ท็อป Linux ของคุณไม่ได้หมายความว่ารุ่น Windows หรือรุ่น Mac จะสร้างขึ้น
โซโลมอนช้า

53

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

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

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


นอกจากนี้ยังมีความต้านทานไวรัสเพิ่มเติม
Joshua

@Joshua อะไรที่ทำให้คุณมีความคิดแบบนั้น?
jpmc26

14
@ jpmc26: เครื่องสร้างติดตั้งซอฟต์แวร์น้อยลงต้องใช้จุดเชื่อมต่อระยะไกลน้อยลงและไม่มีใครเปิดเว็บเบราว์เซอร์ไปยังเว็บไซต์อินเทอร์เน็ตแบบสุ่ม
Joshua

19

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

  • ประการแรกตั้งค่าการเข้าถึงระยะไกลไปยังเซิร์ฟเวอร์สร้าง! หากคุณสร้างด้วยตนเองโดยพิมพ์คำสั่ง "make" หมายความว่าคุณไม่ต้องเดินไปที่สำนักงานอื่นอีกต่อไปเพื่อพิมพ์ "make" คุณสามารถเพียงแค่ SSH ลงในเซิร์ฟเวอร์สร้างและพิมพ์ "make" หากคุณยังไม่ได้ใช้ make หรือระบบบิลด์ที่คล้ายกันให้นำระบบ build นั้นไปใช้
  • ประการที่สองติดตั้งสภาพแวดล้อมการรวมอย่างต่อเนื่องที่ดึงการเปลี่ยนแปลงล่าสุดจากระบบควบคุมเวอร์ชันโดยอัตโนมัติ (คุณมีระบบควบคุมเวอร์ชันใช่ไหมถ้าไม่ใช่นั่นคือขั้นตอนเพิ่มเติม) และสร้างขึ้น ฉันแนะนำ Jenkins ตั้งค่า Jenkins ให้ใช้การทดสอบหน่วยและการทดสอบการรวมระบบในระดับเดียวกัน (คุณมีทั้งคู่ใช่ไหมถ้าไม่ใช่ให้สร้างการทดสอบเริ่มต้นจากการทดสอบหน่วยและสิ้นสุดการทดสอบการรวมระบบระดับ)
  • ประการที่สามหากคุณพบว่าการแบ่งปันเครื่องเดียวกันกับทีมอื่น ๆ นั้นเป็นปัญหา (เช่นถ้าคุณมีความคิดเห็นที่แตกต่างกันเกี่ยวกับระบบปฏิบัติการใดและคุณควรใช้เวอร์ชันใดและความเหมาะสม) ให้พิจารณาใช้ virtualization เซิร์ฟเวอร์ที่ดีในปัจจุบันสามารถใช้งานเครื่องเสมือนจำนวนมากได้ บางทีคุณอาจตั้งค่าเครื่อง 32- บิตและเครื่องจักร 64- ​​บิตเพื่อให้คุณรู้ว่าบิลด์ทำงานบนสถาปัตยกรรมทั้งสอง
  • สุดท้ายนี้อาจไม่จำเป็น: หากคุณต้องมีเครื่องเฉพาะเช่นหากประสิทธิภาพการทำงานของแอปพลิเคชันของคุณมีความสำคัญอย่างยิ่งและการรัน / การสร้าง / ทดสอบอื่น ๆ ที่ทำงานในเวลาเดียวกันส่งผลกระทบต่อผลลัพธ์ของคุณมากเกินไป คุณเท่านั้นที่ใช้ อย่างไรก็ตามในเซิร์ฟเวอร์ล่าสุดที่อาจมีแกน CPU เสมือนมากถึง 40 คอร์หรือมากกว่านั้นมันค่อนข้างจะตรงไปตรงมาในการสร้างเครื่องเสมือนไม่กี่เครื่องที่ไม่แชร์การเข้าถึงคอร์ CPU เดียวกัน

ฉันจะพิจารณาเครื่องที่ใช้ร่วมกันดีกว่าการสร้างด้วยตนเอง โครงการปัจจุบันของฉันใช้เครื่องเสมือนในตอนนี้ แต่เนื่องจากความต้องการการทดสอบประสิทธิภาพการรวมระบบเราจึงย้ายไปที่เซิร์ฟเวอร์เฉพาะที่มี 40 คอร์ CPU เสมือนซึ่งการทดสอบประสิทธิภาพต้องการ 17


16

... แทนที่จะใช้เครื่องจักรจริงในสำนักงานของเราใช้เราต้องแชร์เครื่องเดียวกับกลุ่มอื่น ๆ ...

คุณบอกว่ามันเป็นสิ่งที่ไม่ดี

ตอนนี้คุณมีเซิร์ฟเวอร์บิลด์ทั่วไปที่บิลด์ของคุณและทีมอื่น ๆ ของคุณสร้างขึ้น ความสอดคล้องของการสร้าง? ตรวจสอบ

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

คุณยังคงดำเนินการสร้างด้วยตนเองและไม่ดี

คุณต้องมีกระบวนการเซิร์ฟเวอร์ที่คุณส่ง / ร้องขอคิวเพื่อสร้างสิ่งที่จะทำในนามของคุณและให้กระบวนการนั้นส่งผลลัพธ์กลับมาให้คุณ


5
“ คุณบอกว่ามันเป็นสิ่งที่ไม่ดี” อาจเป็นได้ถ้าพวกเขามีอิสระในการติดตั้งสิ่งที่พวกเขาต้องการขยะ หากพวกเขากำลัง remoting หรือเข้าถึงร่างกายฉันไม่เห็นวิธีที่สามารถป้องกันได้
jpmc26

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

1
ตกลงที่ต้องการมีกระบวนการอัตโนมัติสำหรับการสร้างบิลด์ใหม่ แต่ในเวลาเดียวกันคุณยังต้องการจำลองเอเจนต์บิลด์ของคุณเพื่อให้แน่ใจว่าสภาวะแวดล้อมบิลด์ของคุณอยู่ภายใต้การควบคุมของคุณเอง VMs เป็นเครื่องมือที่ยอดเยี่ยมสำหรับ dev ops และคุณควรใช้ให้เกิดประโยชน์สูงสุด
Voo

@ Voo มันเป็นสถานการณ์กรณีที่เลวร้ายที่สุดมันเป็นกรณีของคนกลาง สิ่งที่ผู้ถามในขณะนี้มีเป็นสถานการณ์กรณีที่เลวร้ายที่สุด (โปรดทราบว่าหากคุณไม่เคยสร้างการสร้างใหม่การอัพเกรดคอมไพเลอร์แบบสุ่มจะไม่เป็นปัญหามากนัก)
user253751

@immibis คุณอ่านส่วนใน parens หลังจากส่วนที่คุณยกมา? มันเป็นสถานการณ์กรณีที่เลวร้ายที่สุดหากมีการสร้างเซิร์ฟเวอร์ที่เกี่ยวข้อง ปัญหาของบั๊กที่ไม่สามารถทำซ้ำได้คือคุณไม่สามารถแก้ไข Hotfix ได้จริง ๆ หากสภาพแวดล้อมการสร้างทั้งหมดของคุณเปลี่ยนไปในระหว่างนี้ นั่นไม่ใช่ปัญหามากนักหากคุณมีเวอร์ชั่นวางจำหน่ายเพียงอันเดียวที่เก็บไว้ใกล้กับลำตัว แต่ในกรณีอื่น ๆ มันก็ค่อนข้างแย่
Voo

1

นอกเหนือจากคำตอบอื่น ๆ ที่เกี่ยวข้องแล้วดูเหมือนว่าคุณกำลังรันงานสร้างของคุณโดยตรงบนเครื่องที่เป็นปัญหา

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


1

มันมีตำแหน่งศูนย์กลางที่เป็นกลางเพื่อดำเนินการสร้างโดยไม่ขึ้นกับ IDE, OS, การกำหนดค่าไลบรารีของนักพัฒนาแต่ละคน

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

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


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