ความต้องการข้อมูลจำเพาะเกี่ยวกับการออกแบบซอฟต์แวร์ลดลงอย่างมีนัยสำคัญเมื่อเทียบกับวิวัฒนาการของภาษาการเขียนโปรแกรมที่แสดงออกได้มากกว่านี้หรือไม่?


16

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

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

ฉันมาถึงข้อสรุปนี้ได้อย่างไร นี่คือข้อโต้แย้งบางอย่าง:

ผลตอบรับ

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

หากไม่มีข้อเสนอแนะมันเป็นการยากที่จะรับรู้และแก้ไขข้อผิดพลาด

ทันทีที่คุณเขียนรหัสคุณจะได้รับข้อเสนอแนะมากมายเช่น:

  • ข้อผิดพลาดและคำเตือนจากคอมไพเลอร์
  • ผลการวิเคราะห์รหัสคงที่
  • การทดสอบหน่วย

สามารถจดจำและแก้ไขข้อผิดพลาดได้อย่างรวดเร็ว

ความมั่นคง

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

refactoring

มีเครื่องมือและเทคนิคที่มีประสิทธิภาพสำหรับการ refactoring code ในขณะที่การ refactoring textual description หรือไดอะแกรมมักจะยากและเกิดข้อผิดพลาดได้ง่าย


มีเงื่อนไขหนึ่งที่จะทำให้งานนี้: รหัสจะต้องง่ายพอที่จะอ่านและทำความเข้าใจ สิ่งนี้อาจไม่สามารถทำได้ด้วย Assembler, Basic หรือ Fortran แต่ภาษาสมัยใหม่ (และห้องสมุด) มีความหมายมากกว่า

ดังนั้นหากข้อโต้แย้งของฉันถูกต้องควรมีแนวโน้มไปสู่ข้อกำหนดและเอกสารการออกแบบซอฟต์แวร์ที่มีน้ำหนักเบาหรือน้อย มีหลักฐานเชิงประจักษ์สำหรับแนวโน้มนี้หรือไม่?


2
การออกแบบตรงไปตรงมาหลุดพ้นจากความนิยมเนื่องจากการพัฒนาความคล่องตัวได้รับความนิยมในขณะที่อุตสาหกรรมครบกำหนด ภาษามีการแสดงออกที่มากขึ้นและเครื่องมือที่มีน้ำหนักเบาทำให้ง่ายขึ้นในการสร้างต้นแบบอย่างรวดเร็วทำให้การพัฒนามีความคล่องตัวมากขึ้น ฉันคิดว่ามีสาเหตุบางอย่างระหว่างทั้งสอง
Reinstate Monica

14
จากประสบการณ์ของฉัน "การสร้างเอกสารการออกแบบอย่างละเอียดที่มีไดอะแกรม UML จำนวนมากก่อนที่จะเขียนบรรทัดโค้ด" ไม่ใช่ความคิดที่ดี - อย่างน้อยก็ไม่ใช่ในเวลาที่ฉันทำงานเป็นโปรแกรมเมอร์มืออาชีพซึ่งมากกว่าหนึ่ง ทศวรรษที่ยาวนานกว่า UML อยู่ Scetching การออกแบบระดับสูงก่อนการเข้ารหัสอย่างไรก็ตามเป็นและเป็นความคิดที่ดีเมื่อระบบคาดว่าจะมีขนาดที่แน่นอน แต่ UML นั้นเป็น IMHO ไม่ใช่เครื่องมือที่เหมาะสมสำหรับสิ่งนี้
Doc Brown

2
ขี้เกียจเกินไปสำหรับคำตอบที่ถูกต้อง: ภาษาการเขียนโปรแกรมที่แสดงออกมากขึ้นและคอมพิวเตอร์ที่มีประสิทธิภาพมากขึ้นนำไปสู่ความต้องการสำหรับโปรแกรมที่มีความสามารถและซับซ้อนมากขึ้นซึ่งนำไปสู่ข้อกำหนดความต้องการที่ซับซ้อนมากขึ้น
whatsisname

2
อ่านที่แนะนำ: ตีค่าเฉลี่ย
Robert Harvey

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

คำตอบ:


9

ฉันตั้งคำถามว่าภาษามีความชัดเจนมากขึ้น ด้วยรหัส ASP.NET ของวันนี้ใน c # ฉันเขียนในระดับเดียวกับที่ฉันทำเมื่อฉันเขียนรหัส ASP ใน Visual Basic เรายังคงใช้ c ++ Javascript ได้เพิ่มคุณสมบัติ แต่ภาษาโดยรวมไม่เปลี่ยนแปลง เหมือนกับ SQL

ฉันคิดว่าการเปลี่ยนแปลงอื่น ๆ เหล่านี้มีความสำคัญมากกว่า:

  1. การยอมรับการทดสอบหน่วยอัตโนมัติ บางคนบอกว่าการทดสอบเป็นข้อกำหนด ดังนั้นเราจึงไม่จำเป็นต้องเขียนสเปคออก ค่อนข้างเราเขียนในรหัสมากกว่าในเอกสาร Word

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

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

  4. สัญญาข้อมูลของ SOA ทุกอย่างสวยมาก ๆ ก็คือ SOA ทุกวันนี้ สิ่งที่คุณต้องมีคือ WSDL วันที่กำหนดและจัดรูปแบบการถ่ายโอนข้อมูลจะหายไป การเคลื่อนไหวในปัจจุบันไปสู่ ​​RESTful และบริการไมโครยังคงแนวโน้มนี้

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

  6. มีการใช้ห้องสมุดที่จัดตั้งขึ้นอย่างมากมาย .NET CLR นำเสนอฟังก์ชันมากมายนอกชั้นวางดังนั้นไม่จำเป็นต้องออกแบบพูดแบบแผนสำหรับการแคชข้อมูลเซสชัน ไลบรารีบุคคลที่สามเช่น jQuery UI หรือ Bootstrap สร้างมาตรฐานสำหรับการเขียนโค้ดเพื่อทำงานในลักษณะที่แน่นอน คุณไม่จำเป็นต้องจัดทำเอกสารเหล่านี้ ทีมควรจะสามารถใช้พวกเขาได้

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

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

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

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


3
อุตสาหกรรมของเราได้ครบกำหนด ... เล็ก ๆ น้อย ๆ รายการที่ 5 คือการเปลี่ยนแปลงที่สำคัญที่สุด มันส่งผลดีต่อผู้อื่นทั้งหมด แต่ความจริงที่ว่าเราเปลี่ยนแปลงเทคโนโลยีทั้งหมดของเราทุก ๆ 5 ปีแสดงให้เห็นว่าเรายังคงมีทางยาวไปและการแสดงออกทางภาษา (สิ่งหนึ่งที่ค่อนข้างคงที่ตลอดเวลาเพราะการปรับปรุงที่มีความหมายในพื้นที่นั้นยากลำบาก) กำไรมากกว่าที่คุณให้เครดิต
Robert Harvey

1
มันไม่ได้เป็นความคืบหน้าทั้งหมด: hopp หลักไปข้างหน้าคืออย่างงดงามด้วยการประดิษฐ์ของคอมไพเลอร์ แต่เรายังคงสอนแผนภูมิการไหลสิ่งที่เป็นนามธรรมเกี่ยวกับรหัสแอสเซมเบลอร์ (และวิธีปฏิบัติที่ล้าสมัยอื่น ๆ ) อาจเป็นเพราะเราลืมทำไม?
ctrl-alt-delor

6

ฉันจะเถียงไม่มี

ด้วยเหตุผลง่ายๆว่า

สำหรับคนไอทีจำนวนมากรวมถึงตัวผมเองเมื่อไม่กี่ปีที่ผ่านมากระบวนการพัฒนาซอฟต์แวร์ที่เหมาะสมจะเกี่ยวข้องกับการสร้างเอกสารการออกแบบอย่างละเอียดพร้อมไดอะแกรม UML จำนวนมากก่อนที่จะมีการเขียนบรรทัดโค้ด

ก็ไม่เคยคิดว่า "อุดมคติ" เช่นการเขียนโปรแกรมมากมีมาตั้งแต่ปี 1990 และตามที่คุณพูดว่า:

ในกรณีที่เหมาะสมไม่ควรมีคำอธิบายของการออกแบบซอฟต์แวร์ยกเว้นรหัสเอง

เคยเถียงกันมานานแล้ว ตัวอย่างบทความตำนานนี้จาก 1992: การออกแบบซอฟแวร์คืออะไร

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

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


6

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

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

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

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


3

ฉันคิดว่าคุณลืมจุดประสงค์ของการมีเอกสารการออกแบบในตอนแรก!

ออกแบบเอกสาร (ข้อกำหนด, กรณีการใช้งาน, การจำลอง ฯลฯ ) ช่วยให้เราสามารถอธิบายทำความเข้าใจและหารือเกี่ยวกับระบบในระดับสูง จำนวนรายละเอียดที่เหลือจากเอกสารดังกล่าวเป็นสิ่งที่ทำให้มีประโยชน์

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

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


แน่นอนว่าต้องมีเอกสารระดับสูงที่ไม่เกี่ยวข้องกับรายละเอียดอย่างแน่นอน แต่นั่นคือสิ่งที่ฉันคาดหวังจากภาษาการเขียนโปรแกรมที่ดี ควรอนุญาตให้เขียนรหัสในระดับรายละเอียดที่แตกต่างกัน รหัสไม่จำเป็นต้องเป็นระเบียบที่ไม่มีโครงสร้างของคำแนะนำระดับต่ำ
Frank Puffer

@FrankPuffer ไดอะแกรมมีมูลค่า 100,000 LoC
RubberDuck

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

1
@RubberDuck: ไดอะแกรมมีเหตุผลในบางกรณีเช่นเพื่ออธิบายสถาปัตยกรรมโดยรวม แต่ฉันไม่คิดว่าพวกเขาควรจะเป็นค่าเริ่มต้น มีไดอะแกรมที่ดีและมีประโยชน์ แต่น่าเสียดายที่ UML ส่วนใหญ่ที่ฉันเห็นมีความสับสนมากกว่าที่เป็นประโยชน์ และสิ่งที่แย่กว่านั้นก็มักจะแตกต่างจากการใช้งานจริง
Frank Puffer

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

1

ในกรณีที่เหมาะสมไม่ควรมีคำอธิบายของการออกแบบซอฟต์แวร์ยกเว้นรหัสเอง

สิ่งนี้ไกลเกินกว่าที่คุณบอกเป็นนัย แม้กระทั่งสิ่งต่าง ๆ เช่นประเภทตาม (ซึ่งอย่างที่ฉันเข้าใจมันค่อนข้างเป็นไปตามหลักวิชาในเชิงทฤษฎี) ก็เป็นเวลาหลายปี

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

การทดสอบหน่วย

หากการทดสอบอสังหาริมทรัพย์ไม่เป็นที่นิยมฉันไม่คิดว่าการดำเนินการนี้จะเป็นจริงมานาน

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

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

อาจจะง่ายกว่าในการใช้เครื่องมือทดสอบเอกสารในขณะนี้

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

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

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

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