วิธีจัดการความซับซ้อนโดยไม่ตั้งใจในโครงการซอฟต์แวร์


74

เมื่อ Murray Gell-Mann ถูกถามว่า Richard Feynman จัดการเพื่อแก้ไขปัญหาที่ยากมากมายได้อย่างไร Gell-Mann ตอบว่า Feynman มีอัลกอริทึม:

  1. จดบันทึกปัญหา
  2. คิดหนักจริง
  3. เขียนวิธีการแก้ปัญหา

Gell-Mann พยายามอธิบายว่า Feynman เป็นนักแก้ปัญหาที่แตกต่างกันและไม่มีความเข้าใจที่จะได้รับจากการศึกษาวิธีการของเขา ฉันรู้สึกแบบเดียวกันกับการจัดการความซับซ้อนในโครงการซอฟต์แวร์ขนาดกลาง / ใหญ่ ผู้คนที่ดีนั้นดีโดยกำเนิดและจัดการกับเลเยอร์และสแต็ค abstractions ต่าง ๆ เพื่อให้ทุกอย่างสามารถจัดการได้โดยไม่ต้องแนะนำ cruft ที่ไม่เกี่ยวข้องใด ๆ

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


32
ฉันจะไม่แปลกใจถ้าการจดบันทึกปัญหา (และแก้ไขมันให้ดีเพื่อที่คุณจะสามารถอธิบายให้คนอื่นฟังได้อย่างเพียงพอ) ช่วยคุณระบุวิธีแก้ปัญหา
Rory Hunter

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

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

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

2
@CortAmmon ไม่ควรหมายความว่าเป็นเรื่องจริง 99% ของสิ่งที่นักพัฒนารู้ว่าได้เรียนรู้ในบางช่วงผ่านการเติบโตแบบ on-the-fly ของคุณ ใช้ตัวแก้ปัญหาที่ดีในการสร้างโปรแกรมเมอร์ที่ดี การแก้ปัญหาคือสิ่งที่เราตั้งใจจะทำ หากนักพัฒนาของคุณไม่เติบโตพวกเขาอาจทำงานซ้ำ ๆ ที่น่าเบื่อมากมาย ประเภทของงานที่จะทำให้นักพัฒนาที่มีความสามารถมีเหตุผลไม่มีความสุขและหดหู่ และ ... 'Spiral Development' ไม่ได้เป็นเพียงแค่แนวคิดพื้นฐานของการพัฒนาแบบวนซ้ำกับเหตุการณ์สำคัญของน้ำตก
Evan Plaice

คำตอบ:


104

เมื่อคุณเห็นการเคลื่อนไหวที่ดีให้มองหาสิ่งที่ดีกว่า
—Emanuel Lasker แชมป์หมากรุกโลก 27 ปี

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

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

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

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


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

1
TL; DR; refactor ไม่กลัว
ocodo

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

46

"ทักษะสถาปัตยกรรมซอฟต์แวร์ไม่สามารถสอนได้" เป็นความเข้าใจผิดอย่างกว้างขวาง

เป็นเรื่องง่ายที่จะเข้าใจว่าทำไมหลายคนเชื่อ (คนที่เก่งและอยากจะเชื่อว่าพวกเขามีความพิเศษอย่างลึกลับและผู้ที่ไม่ต้องการเชื่อว่าไม่ใช่ความผิดของพวกเขาที่พวกเขาไม่ได้เป็น) เป็นสิ่งที่ผิด ทักษะนั้นค่อนข้างจะใช้ฝึกได้มากกว่าทักษะซอฟต์แวร์อื่น ๆ (เช่นการทำความเข้าใจลูปการจัดการกับพอยน์เตอร์ ฯลฯ )

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

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


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

26
"การตัดสินที่ดีมาจากประสบการณ์ประสบการณ์มาจากการตัดสินที่ไม่ดี" --Mulla Nasrudin
Jonas Kölker

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

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

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

22

การคิดเชิงปฏิบัติโดย Andy Huntแก้ปัญหานี้ได้ มันหมายถึงโมเดล Dreyfus ตามที่มีความเชี่ยวชาญใน 5 ขั้นตอนในทักษะต่าง ๆ สามเณร (ด่าน 1) ต้องการคำแนะนำที่แม่นยำเพื่อให้สามารถทำอะไรบางอย่างได้อย่างถูกต้อง ในทางตรงกันข้ามผู้เชี่ยวชาญ (ด่าน 5) สามารถใช้รูปแบบทั่วไปกับปัญหาที่กำหนด อ้างถึงหนังสือ

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

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

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

คำถามจากที่ทำงานมีความเกี่ยวข้องและ IMHO น่าสนใจที่จะอ่านในบริบทนี้


3
ช่างเป็นคำอธิบายที่ยอดเยี่ยมเกี่ยวกับความคิดของผู้เชี่ยวชาญ มันไม่ใช่เรื่องมหัศจรรย์จริง ๆ มันแค่ยากที่จะบอกขั้นตอนที่ไม่ต่อเนื่องและตรรกะทั้งหมด
MetaFight


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

1
@Dunk, Magic จะเป็นเมื่อนักกีฬา "ผู้ดี" เหล่านั้นสามารถทำสิ่งเดียวกันได้โดยไม่ต้องมีการฝึกอบรมใด ๆ เลย แนวคิดหลักคือไม่มีกระสุนเงิน ไม่ว่าคนที่มีความสามารถมากเพียงใดก็ตามไม่สามารถรับประสบการณ์เพียงแค่ศึกษา "ขั้นตอนที่ไม่ต่อเนื่องและเชิงตรรกะ" โดยวิธีการตามหนังสือเล่มเดียวกันเพียง 1-5% ของคนที่เป็นผู้เชี่ยวชาญ
superM

@Super: ฉันจะถามหนังสือ / การศึกษาใด ๆ ที่ทำให้การเรียกร้องที่ไร้สาระเช่นนี้เพียง 1-5% ของคนที่เป็นผู้เชี่ยวชาญ พูดคุยเกี่ยวกับการดึงตัวเลขออกจาก # & # & $ # ผู้เชี่ยวชาญอะไร ฉันพนันได้เลยว่าคนที่มีความเชี่ยวชาญด้านการหายใจการเดินการรับประทานอาหารมีเปอร์เซ็นต์ที่สูงขึ้นมาก ใครเป็นผู้ตัดสินระดับผู้เชี่ยวชาญ? การอ้างสิทธิ์เช่น 1-5% ทำให้เสียการอ้างสิทธิ์และการวิเคราะห์เพิ่มเติมใด ๆ โดยผู้เขียนดังกล่าว
Dunk

4

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

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

ที่จริงแล้วอัลกอริทึมไฟน์แมนใช้ในระดับหนึ่ง แต่นั่นไม่ได้หมายความว่า "คิดหนักจริง" หมายถึงเวทมนต์ที่ไม่สามารถประมวลผลได้

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

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

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

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

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

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

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


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

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

3

" ทุกสิ่งควรทำอย่างเรียบง่ายที่สุดเท่าที่จะทำได้ แต่ไม่ง่ายกว่านี้ "
- ประกอบกับ Albert Einstein

ให้ฉันวาดอัลกอริทึมส่วนตัวของฉันสำหรับจัดการกับความซับซ้อนโดยไม่ตั้งใจ

  1. เขียนเรื่องราวของผู้ใช้หรือกรณีการใช้งาน ตรวจสอบกับเจ้าของผลิตภัณฑ์
  2. เขียนการทดสอบการรวมที่ล้มเหลวเนื่องจากไม่มีคุณสมบัติ ตรวจสอบกับ QA หรือหัวหน้าวิศวกรหากมีสิ่งนั้นในทีมของคุณ
  3. เขียนการทดสอบหน่วยสำหรับบางคลาสที่สามารถผ่านการทดสอบการรวม
  4. เขียนการใช้งานที่น้อยที่สุดสำหรับคลาสเหล่านั้นที่ผ่านการทดสอบหน่วย
  5. ตรวจสอบการทดสอบหน่วยและการใช้งานกับนักพัฒนาซอฟต์แวร์เพื่อน ไปที่ขั้นตอนที่ 3

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

น่าแปลกใจเพียงแค่จินตนาการว่าคุณมีทางออกดูเหมือนจะเป็นหนึ่งในคำแนะนำหลักของคนที่เขียนเกี่ยวกับการแก้ปัญหา (เรียกว่า "การคิดปรารถนา" โดย Abelson และ Sussman ในโครงสร้างและการตีความโปรแกรมคอมพิวเตอร์และ "ทำงานย้อนหลัง" ใน Polya's How to แก้มัน )

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

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


2

ความซับซ้อนของอุบัติเหตุ

คำถามเดิม (ถอดความ) คือ:

สถาปนิกจัดการความซับซ้อนโดยไม่ตั้งใจในโครงการซอฟต์แวร์ได้อย่างไร

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

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

หลีกเลี่ยงความซับซ้อนที่ไม่จำเป็น

จากเนื้อหาของคำถามฉันจะใช้ถ้อยคำใหม่เช่นนี้:

สถาปนิกจัดการความซับซ้อนในโครงการซอฟต์แวร์อย่างไร

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

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

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

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

สร้างโซลูชัน

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

กลับไปที่คำถามสุดท้ายที่เฉพาะเจาะจง:

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

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


"gestalt" หมายความว่าอะไร? ฉันพบว่ามันเหมือนกับ "กระบวนทัศน์" - ใช้ในทางที่ผิดหรือมักจะให้อะไรบางอย่างกับบรรยากาศของสถาบันการศึกษา


0

นี่อาจเป็นคำถามที่ยากเมื่อหลายปีก่อน แต่ในปัจจุบัน IMO ก็ไม่ยากที่จะกำจัดความซับซ้อนโดยไม่ตั้งใจ

สิ่งที่ Kent Becksaid เกี่ยวกับตัวเองในบางจุด: "ฉันไม่ใช่โปรแกรมเมอร์ที่ยอดเยี่ยม; ฉันเป็นโปรแกรมเมอร์ที่ดีและมีนิสัยที่ดี"

สองสิ่งที่ควรค่าแก่การเน้น IMO: เขาคิดว่าตัวเองเป็นโปรแกรมเมอร์ไม่ใช่สถาปนิกและการมุ่งเน้นของเขาก็คือนิสัยไม่ใช่ความรู้

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

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

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

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

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