ฉันก็ 'ฉลาด' เหมือนกันที่จูเนียร์ devs สามารถอ่านได้หรือไม่? การเขียนโปรแกรมที่ใช้งานได้มากเกินไปใน JS ของฉัน? [ปิด]


133

ฉันเป็นนักพัฒนาซอฟต์แวร์ระดับสูงที่เข้ารหัสใน Babel ES6 ส่วนหนึ่งของแอปของเราทำการเรียก API และตามแบบจำลองข้อมูลที่เราได้รับกลับมาจากการเรียก API ต้องกรอกแบบฟอร์มบางอย่าง

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

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

นี่คือวิธีที่ฉันคิดว่าโปรแกรมเมอร์มือใหม่จะจัดการกับมัน

export const addPages = (apiData) => {
   let pagesList = new PagesList(); 

   if(apiData.pages.foo){
     pagesList.add('foo', apiData.pages.foo){
   }

   if (apiData.pages.arrayOfBars){
      let bars = apiData.pages.arrayOfBars;
      bars.forEach((bar) => {
         pagesList.add(bar.name, bar.data);
      })
   }

   if (apiData.pages.customBazes) {
      let bazes = apiData.pages.customBazes;
      bazes.forEach((baz) => {
         pagesList.add(customBazParser(baz)); 
      })
   } 

   return pagesList;
}

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

ตอนนี้ทดสอบได้สิ่งหนึ่ง แต่ก็อ่านได้และฉันสงสัยว่าฉันทำสิ่งที่อ่านได้น้อยลงที่นี่

// file: '../util/functor.js'

export const Identity = (x) => ({
  value: x,
  map: (f) => Identity(f(x)),
})

// file 'addPages.js' 

import { Identity } from '../util/functor'; 

export const parseFoo = (data) => (list) => {
   list.add('foo', data); 
}

export const parseBar = (data) => (list) => {
   data.forEach((bar) => {
     list.add(bar.name, bar.data)
   }); 
   return list; 
} 

export const parseBaz = (data) => (list) => {
   data.forEach((baz) => {
      list.add(customBazParser(baz)); 
   })
   return list;
}


export const addPages = (apiData) => {
   let pagesList = new PagesList(); 
   let { foo, arrayOfBars: bars, customBazes: bazes } = apiData.pages; 

   let pages = Identity(pagesList); 

   return pages.map(foo ? parseFoo(foo) : x => x)
               .map(bars ? parseBar(bars) : x => x)
               .map(bazes ? parseBaz(bazes) : x => x)
               .value

}

นี่คือความกังวลของฉัน สำหรับฉันด้านล่างมีการจัดระเบียบมากขึ้น รหัสตัวเองแตกออกเป็นชิ้นเล็ก ๆ ที่สามารถทดสอบแยกได้ แต่ฉันคิดว่า: ถ้าฉันต้องอ่านว่าในฐานะนักพัฒนารุ่นเยาว์ที่ไม่คุ้นเคยกับแนวคิดเช่นการใช้ Identity functors, currying, หรือข้อความที่ประกอบไปด้วยสามคำฉันจะเข้าใจได้หรือไม่ว่าคำตอบหลังนั้นทำอะไร? จะดีกว่าไหมในการทำสิ่งที่ผิดพลาดง่ายขึ้น?


13
ในฐานะคนที่มีการสอนตัวเองเพียง 10 ปีใน JS ฉันจะถือว่าตัวเองเป็นจูเนียร์และคุณทำให้ฉันหลงBabel ES6
ไหล

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

15
ฉันแค่ต้องการอ้างถึง Brian Kerninghan ที่นี่: "ทุกคนรู้ดีว่าการดีบั๊กนั้นยากกว่าการเขียนโปรแกรมตั้งแต่แรกดังนั้นถ้าคุณฉลาดเท่าที่จะเป็นเมื่อคุณเขียนมันคุณจะดีบั๊กอย่างไร? " - en.wikiquote.org/wiki/Brian_Kernighan / "องค์ประกอบของรูปแบบการเขียนโปรแกรม", รุ่นที่ 2, บทที่ 2
MarkusSchaber

7
@Logister Coolness ไม่ได้เป็นเป้าหมายหลักมากกว่าความเรียบง่าย การคัดค้านที่นี่คือความซับซ้อนที่ไม่ต้องเสียค่าใช้จ่ายซึ่งเป็นศัตรูของความถูกต้อง (เป็นข้อกังวลหลัก) เพราะมันทำให้รหัสยากขึ้นที่จะให้เหตุผลและมีแนวโน้มที่จะมีกรณีมุมที่ไม่คาดคิด ด้วยความสงสัยที่กล่าวไว้ก่อนหน้านี้ของฉันเกี่ยวกับการอ้างว่าจริง ๆ แล้วง่ายต่อการทดสอบฉันไม่เคยเห็นข้อโต้แย้งที่น่าเชื่อถือสำหรับรูปแบบนี้ ในการเปรียบเทียบกับกฎความปลอดภัย wrt สิทธิพิเศษอย่างน้อยบางทีอาจมีกฎง่ายๆที่บอกว่าเราควรระวังการใช้คุณสมบัติภาษาที่มีประสิทธิภาพเพื่อทำสิ่งที่ง่าย
sdenham

6
รหัสของคุณดูเหมือนโค้ดจูเนียร์ ฉันคาดว่าผู้อาวุโสจะเขียนตัวอย่างแรก
sed

คำตอบ:


322

ในรหัสของคุณคุณทำการเปลี่ยนแปลงหลายอย่าง:

  • destructuring มอบหมายการเข้าถึงเขตข้อมูลในการpagesเปลี่ยนแปลงที่ดี
  • การแยกparseFoo()ฟังก์ชั่น ฯลฯ อาจเป็นการเปลี่ยนแปลงที่ดี
  • การแนะนำนักแสดงคือ ... สับสนมาก

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

สิ่งที่ฉันคาดหวังให้เห็นแทน:

if (foo) parseFoo(pages, foo);
if (bars) parseBar(pages, bars);
if (bazes) parseBaz(pages, bazes);
return pages;

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

pages.addAll(parseFoo(foo));
pages.addAll(parseBar(bars));
pages.addAll(parseBaz(bazes));
return pages;

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

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

กรุณา: หากมีข้อสงสัยให้รหัสของคุณง่ายและโง่ (หลักการ KISS)


2
จากจุดสมมาตรในมุมมองของสิ่งที่ไม่let pages = Identity(pagesList)ได้แตกต่างจากparseFoo(foo)? ระบุว่าผมก็อาจจะมี {Identity(pagesList), parseFoo(foo), parseBar(bar)}.flatMap(x -> x)...
ArTs

8
ขอบคุณที่อธิบายว่าการใช้แลมบ์ดาซ้อนกันสามครั้งเพื่อรวบรวมรายการที่แมป (ไปยังตาที่ไม่ได้รับการฝึกฝนของฉัน) อาจจะฉลาดเกินไป
Thorbjørn Ravn Andersen

2
ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
yannis

บางทีสไตล์ที่คล่องแคล่วอาจทำงานได้ดีในตัวอย่างที่สองของคุณ?
user1068

225

หากคุณมีข้อสงสัยมันอาจฉลาดเกินไป! ตัวอย่างที่สองนำเสนอความซับซ้อนโดยไม่ตั้งใจด้วยนิพจน์เช่นfoo ? parseFoo(foo) : x => xและรหัสโดยรวมมีความซับซ้อนมากขึ้นซึ่งหมายความว่าเป็นการยากที่จะติดตาม

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

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

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

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


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

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

14
ฉันไม่คิดว่ารหัสที่ฉลาดเป็นสิ่งที่แสดงออกมา บางครั้งมันรู้สึกเป็นธรรมชาติและดูไร้สาระในการตรวจสอบครั้งที่สอง

5
ฉันได้ลบถ้อยคำเกี่ยวกับ "การแสดง" ออกไปเพราะฟังดูมีวิจารณญาณมากกว่าที่ตั้งใจไว้
JacquesB

11
@ BaileyS - ฉันคิดว่าเน้นความสำคัญของการตรวจสอบโค้ด สิ่งที่ให้ความรู้สึกเป็นธรรมชาติและตรงไปตรงมากับ coder โดยเฉพาะอย่างยิ่งเมื่อมีการพัฒนาแบบค่อยเป็นค่อยไปสามารถดูได้ง่าย ๆ กับผู้ตรวจสอบ รหัสนั้นจะไม่ผ่านการตรวจสอบจนกว่าจะมีการสร้างใหม่ / เขียนใหม่เพื่อลบการสนทนา
Myles

21

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

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

และถ้านั่นคือทั้งหมดที่มีให้ทำไมต้องใช้identity functionกับternary operatorหรือใช้functorสำหรับการแยกวิเคราะห์ข้อมูล? นอกจากนี้ทำไมคุณถึงคิดว่ามันเป็นวิธีการที่เหมาะสมในการนำไปใช้functional programmingที่ทำให้เกิดผลข้างเคียง (โดยการปิดรายการ) ทำไมทุกสิ่งเมื่อคุณต้องการเพียงแค่นี้:

const processFooPages = (foo) => foo ? [['foo', foo]] : [];
const processBarPages = (bar) => bar ? bar.map(page => [page.name, page.data]) : [];
const processBazPages = (baz) => baz ? baz.map(page => [page.id, page.content]) : [];

const addPages = (apiData) => {
  const list = new PagesList();
  const pages = [].concat(
    processFooPages(apiData.pages.foo),
    processBarPages(apiData.pages.arrayOfBars),
    processBazPages(apiData.pages.customBazes)
  );
  pages.forEach(([pageName, pageContent]) => list.addPage(pageName, pageContent));

  return list;
}

(jsfiddle ที่รันได้ที่นี่ )

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

ตอนนี้เปรียบเทียบโค้ดนี้กับสิ่งที่คุณคิดไว้ข้างต้นคุณเห็นความแตกต่างหรือไม่ ไม่ต้องสงสัยfunctional programmingและไวยากรณ์ของ ES6 นั้นมีประสิทธิภาพ แต่ถ้าคุณตัดปัญหาด้วยวิธีที่ไม่ถูกต้องด้วยเทคนิคเหล่านี้คุณจะพบกับรหัสที่ยุ่งกว่า

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


2
+1 สำหรับการชี้ให้เห็นถึงทัศนคติที่กว้างขวาง (ไม่จำเป็นต้องใช้กับ OP): "เพียงเพราะคุณกำลังใช้เทคนิค ES6 ล่าสุดหรือการใช้กระบวนทัศน์การเขียนโปรแกรมที่ได้รับความนิยมสูงสุดไม่จำเป็นต้องหมายความว่ารหัสของคุณถูกต้องมากขึ้น หรือรหัสจูเนียร์นั้นผิด ".
จอร์โจ

+1 คุณสามารถใช้โอเปอเรเตอร์การกระจาย (... ) แทน _.concat เพื่อลบการอ้างอิงนั้น
YoTengoUnLCD

1
@YoTengoUnLCD อ่าเยี่ยมมาก ตอนนี้คุณก็รู้แล้วว่าฉันและทีมของฉันยังคงเดินทางlodashโดยไม่ได้รับประโยชน์จากการใช้งานของเรา รหัสนั้นสามารถใช้งานspread operatorได้หรือแม้ว่าจะ[].concat()ต้องการรักษารูปร่างของรหัสให้เหมือนเดิม
b0nyb0y

ขออภัยรายชื่อรหัสนี้ยังไม่ชัดเจนสำหรับฉันมากไปกว่า "รหัสรุ่นใหม่" ในโพสต์ของ OP โดยทั่วไป: อย่าใช้ผู้ประกอบการที่สามถ้าคุณสามารถหลีกเลี่ยงได้ มันเครียดเกินไป ในภาษาที่ใช้งานได้จริงคำสั่ง if-statement จะเป็นนิพจน์และไม่ใช่ statement และสามารถอ่านได้มากขึ้น
Olle Härstedt

@ OlleHärstedtอืมนั่นเป็นสิ่งที่คุณสนใจ สิ่งที่เป็นกระบวนทัศน์การเขียนโปรแกรมฟังก์ชั่นหรือกระบวนทัศน์ใด ๆ ออกมีไม่เคยผูกลงกับภาษาการทำงาน "จริง" ใด ๆ โดยเฉพาะน้อยกว่าไวยากรณ์ของมัน ดังนั้นการกำหนดว่าการสร้างแบบมีเงื่อนไขควรหรือไม่ควรใช้แบบ "ไม่เคย" แต่ก็ไม่สมเหตุสมผล A ternary operatorใช้ได้เหมือนifคำสั่งปกติไม่ว่าคุณจะชอบหรือไม่ก็ตาม การอภิปรายการอ่านระหว่างif-elseและ?:ค่ายที่ไม่มีที่สิ้นสุดดังนั้นฉันจะไม่ได้รับความเป็นมัน ทั้งหมดที่ฉันจะพูดคือด้วยสายตาที่ได้รับการฝึกฝนเส้นแบบนี้แทบจะไม่ "เครียดเกินไป"
b0nyb0y

5

ตัวอย่างที่สองไม่สามารถทดสอบได้มากกว่าตัวอย่างแรก การตั้งค่าการทดสอบที่จำเป็นทั้งหมดสำหรับตัวอย่างโค้ดหนึ่งในสองรายการนั้นเป็นเรื่องตรงไปตรงมา

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

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


3

TD; DR

  1. คุณสามารถอธิบายรหัสของคุณให้ผู้พัฒนาระดับสูงในเวลาน้อยกว่า 10 นาทีได้หรือไม่?
  2. สองเดือนจากนี้คุณสามารถเข้าใจรหัสของคุณหรือไม่

การวิเคราะห์รายละเอียด

ความชัดเจนและอ่านง่าย

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

การอ่านส่วนใหญ่จะขึ้นอยู่กับความคุ้นเคยไม่บางนับคณิตศาสตร์ของสัญญาณ IMO ในระยะนี้คุณมี ES6 มากเกินไปในการเขียนใหม่ บางทีในอีกไม่กี่ปีข้างหน้าฉันจะเปลี่ยนคำตอบของฉัน :-) BTW ฉันชอบ @ b0nyb0y คำตอบที่เหมาะสมและชัดเจน

การตรวจสอบได้

if(apiData.pages.foo){
   pagesList.add('foo', apiData.pages.foo){
}

สมมติว่า PagesList.add () มีการทดสอบซึ่งควรจะเป็นรหัสตรงไปตรงมาอย่างสมบูรณ์และไม่มีเหตุผลที่ชัดเจนสำหรับส่วนนี้ที่จะต้องมีการทดสอบแยกต่างหากเป็นพิเศษ

if (apiData.pages.arrayOfBars){
      let bars = apiData.pages.arrayOfBars;
      bars.forEach((bar) => {
         pagesList.add(bar.name, bar.data);
      })
   }

อีกครั้งฉันไม่เห็นความจำเป็นในทันทีสำหรับการทดสอบแยกต่างหากในหัวข้อนี้ เว้นแต่ PagesList.add () มีปัญหาที่ผิดปกติกับโมฆะหรือซ้ำซ้อนหรืออินพุตอื่น

if (apiData.pages.customBazes) {
      let bazes = apiData.pages.customBazes;
      bazes.forEach((baz) => {
         pagesList.add(customBazParser(baz)); 
      })
   } 

รหัสนี้ก็ตรงไปตรงมามาก สมมติว่าcustomBazParserผ่านการทดสอบและไม่ส่งคืนผลลัพธ์ "พิเศษ" มากเกินไป ดังนั้นอีกครั้งเว้นแต่มีสถานการณ์ที่ยุ่งยากด้วย `PagesList.add (), (ซึ่งอาจเป็นเพราะฉันไม่คุ้นเคยกับโดเมนของคุณ) ฉันไม่เห็นว่าทำไมส่วนนี้จึงจำเป็นต้องมีการทดสอบพิเศษ

โดยทั่วไปการทดสอบฟังก์ชั่นทั้งหมดจะทำงานได้ดี

ข้อจำกัดความรับผิดชอบ : หากมีเหตุผลพิเศษในการทดสอบความเป็นไปได้ทั้ง 8 ข้อของทั้งสามif()ข้อความแล้วใช่จะทำการทดสอบแยกกัน หรือถ้าPagesList.add()อ่อนไหวใช่แบ่งการทดสอบออก

โครงสร้าง: มันคุ้มค่าที่จะแบ่งออกเป็นสามส่วน (เช่นกอล)

ที่นี่คุณมีข้อโต้แย้งที่ดีที่สุด โดยส่วนตัวฉันไม่คิดว่ารหัสดั้งเดิมนั้น "ยาวเกินไป" (ฉันไม่ใช่คนคลั่ง SRP) แต่ถ้ามีอีกไม่กี่if (apiData.pages.blah)ส่วน SRP จะทำการตรวจสอบอีกครั้งว่ามันน่าเกลียดและมันก็คุ้มค่าที่จะแยกกัน โดยเฉพาะอย่างยิ่งถ้าใช้ DRY และสามารถใช้ฟังก์ชันในตำแหน่งอื่นของรหัสได้

ข้อเสนอแนะหนึ่งของฉัน

YMMV ในการบันทึกบรรทัดของรหัสและตรรกะบางอย่างฉันอาจรวมifและปล่อยให้เป็นหนึ่งบรรทัด: เช่น

let bars = apiData.pages.arrayOfBars || [];
bars.forEach((bar) => {
   pagesList.add(bar.name, bar.data);
})

สิ่งนี้จะล้มเหลวหาก apiData.pages.arrayOfBars เป็นตัวเลขหรือสตริง แต่จะเป็นรหัสต้นฉบับ และสำหรับฉันมันชัดเจนกว่า (และสำนวนที่ใช้มากเกินไป)

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