ความแตกต่างระหว่าง Declarative และ Imperative ใน React.js?


97

เมื่อเร็ว ๆ นี้ฉันได้ศึกษามากมายเกี่ยวกับฟังก์ชันการทำงานและวิธีการใช้ไลบรารี Facebook JavaScript React.js เมื่อพูดถึงความแตกต่างของส่วนที่เหลือของโลกจาวาสคริปต์มักจะเป็นสองรูปแบบการเขียนโปรแกรมdeclarativeและimperativeจะ mentionned

อะไรคือความแตกต่างระหว่างทั้งสอง?


22
latentflip.com/imperative-vs-declarative Imperative programming: telling the "machine" how to do something, and as a result what you want to happen will happen. Declarative programming: telling the "machine"1 what you would like to happen, and let the computer figure out how to do it.
rickyduck

4
Tyler McGinnis เขียนบทความยาว ๆเกี่ยวกับเรื่องนี้พร้อมกับตัวอย่างที่ดี
Ian Dunn

เพิ่มคำตอบยาว ๆ ใน
อเล็กซ์

1
ลิงก์ด้านบนถูกต้อง แต่เครื่องหมายทับที่รวมอยู่ในลิงก์ทำให้เกิด 404 latentflip.com/imperative-vs-declarative
James Yoo

คำตอบ:


167

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

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

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

Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table

ในโลกแห่งการประกาศคุณเพียงแค่อธิบายสิ่งที่คุณต้องการ

I want dinner with chicken.

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

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


78

ลองนึกภาพส่วนประกอบ UI ง่ายๆเช่นปุ่ม "ถูกใจ" เมื่อคุณแตะจะเปลี่ยนเป็นสีน้ำเงินหากก่อนหน้านี้เคยเป็นสีเทาและเป็นสีเทาหากก่อนหน้านี้เป็นสีน้ำเงิน

วิธีที่จำเป็นในการทำสิ่งนี้คือ:

if( user.likes() ) {
    if( hasBlue() ) {
        removeBlue();
        addGrey();
    } else {
        removeGrey();
        addBlue();
    }
}

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

ในทางตรงกันข้ามวิธีการประกาศจะเป็น:

if( this.state.liked ) {
    return <blueLike />;
} else {
    return <greyLike />;
}

เนื่องจากวิธีการที่เปิดเผยแยกความกังวลส่วนนี้จึงจำเป็นต้องจัดการว่า UI ควรมีลักษณะอย่างไรในสถานะเฉพาะเท่านั้นดังนั้นจึงเข้าใจง่ายกว่ามาก


21

นี่เป็นการเปรียบเทียบที่ยอดเยี่ยม:

* คำตอบที่จำเป็น : ออกจากทางออกด้านทิศเหนือของที่จอดรถแล้วเลี้ยวซ้าย เดินทางบน I-15 ไปทางทิศใต้จนถึงทางออก Bangerter Highway เดินออกจากทางออกทันทีเหมือนไป Ikea ตรงไปเลี้ยวขวาที่แสงแรก ผ่านไฟถัดไปจากนั้นเลี้ยวซ้ายถัดไป บ้านของฉันคือ # 298

คำตอบที่เปิดเผย : ที่อยู่ของฉันคือ 298 West Immutable Alley, Draper Utah 84020 *

https://tylermcginnis.com/imperative-vs-declarative-programming/


18

ที่ดีที่สุดคือเปรียบเทียบ React (เชิงประกาศ) และ JQuery (จำเป็น) เพื่อแสดงความแตกต่าง

ในการตอบสนองคุณจะต้องอธิบายสถานะสุดท้ายของ UI ในrender()วิธีการเท่านั้นโดยไม่ต้องกังวลเกี่ยวกับวิธีการเปลี่ยนจากสถานะ UI ก่อนหน้าไปเป็นสถานะ UI ใหม่ เช่น,

render() {
  const { price, volume } = this.state;
  const totalPrice = price * volume;

  return (
    <div>
      <Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
      <Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
      <Label value={totalPrice} ... />
      ...
    </div>
  )
}

ในทางกลับกัน JQuery ต้องการให้คุณเปลี่ยนสถานะ UI ของคุณโดยจำเป็นเช่นการเลือกองค์ประกอบป้ายกำกับและอัปเดตข้อความและ CSS:

updatePrice(price) {
  $("#price-label").val(price);
  $("#price-label").toggleClass('expansive', price > 100);
  $("#price-label").toggleClass('cheap', price < 100);

  // also remember to update UI depending on price 
  updateTotalPrice();
  ... 
}

updateVolume(volume) {
  $("#volume-label").val(volume);
  $("#volume-label").toggleClass('high', volume > 1000);
  $("#volume-label").toggleClass('low', volume < 1000);
  
  // also remember to update UI depending on volume
  updateTotalPrice();
  ... 
}

updateTotalPrice() {
  const totalPrice = price * volume;
  $("#total-price-label").val(totalPrice);
  ...
}

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

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

  • ภายใต้เบ็ด React จะอัปเดตองค์ประกอบ DOM ที่เปลี่ยนแปลงทั้งหมดโดยใช้รหัสที่จำเป็น

คุณยังสามารถอ่านคำตอบของฉันสำหรับอะไรคือความแตกต่างระหว่างการเขียนโปรแกรมเชิงประกาศและแบบจำเป็น?.

PS: จากตัวอย่าง jQuery ด้านบนคุณอาจคิดว่าถ้าเราใส่การปรับแต่ง DOM ทั้งหมดในupdateAll()เมธอดและเรียกมันทุกครั้งเมื่อสถานะแบบจำลองใด ๆ ของเราเปลี่ยนไปและ UI จะไม่ซิงค์กัน คุณถูกต้องและนี่คือสิ่งที่ React ทำได้อย่างมีประสิทธิภาพความแตกต่างเพียงอย่างเดียวคือ jQuery updateAll()จะทำให้เกิดการปรับแต่ง DOM ที่ไม่จำเป็นมากมาย แต่ React จะอัปเดตองค์ประกอบ DOM ที่เปลี่ยนแปลงโดยใช้อัลกอริธึมเสมือน DOM Diffingเท่านั้น


6

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

การตอบสนองเป็นประกาศเนื่องจากเราเขียนโค้ดที่เราต้องการและ React รับผิดชอบในการรับโค้ดที่ประกาศของเราและดำเนินการตามขั้นตอน JavaScript / DOM ทั้งหมดเพื่อให้เราได้ผลลัพธ์ที่ต้องการ


5

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

- เอาแก้วจากชั้นวาง

- วางแก้วไว้หน้าร่าง

- ดึงที่จับลงจนเต็มกระจก

- ส่งแก้วมาให้ฉัน

ในโลกแห่งการประกาศคุณจะพูดว่า: "เบียร์ได้โปรด"

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

ในการเขียนโปรแกรมเชิงประกาศนักพัฒนาจะอธิบายเฉพาะสิ่งที่ต้องการบรรลุเท่านั้นและไม่จำเป็นต้องระบุขั้นตอนทั้งหมดเพื่อให้มันใช้งานได้

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

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


1

การเขียนโปรแกรมแบบสำแดงเป็นกระบวนทัศน์การเขียนโปรแกรม ... ที่แสดงตรรกะของการคำนวณโดยไม่ต้องอธิบายขั้นตอนการควบคุม

การเขียนโปรแกรมที่จำเป็นคือกระบวนทัศน์การเขียนโปรแกรมที่ใช้คำสั่งที่เปลี่ยนสถานะของโปรแกรม

ลิงค์อ้างอิง: - https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2


0

ฉันจะเริ่มด้วยการเปรียบเทียบ: ฉันมีรถสองคันในรถสองคันของฉันฉันต้องการให้อุณหภูมิภายในรถเป็นอุณหภูมิห้องปกติ ~ 72 ° F ในรถคันแรก (รุ่นเก่า) จะมีปุ่มควบคุมอุณหภูมิ 2 ปุ่ม (1 ปุ่มควบคุมอุณหภูมิและ 1 ปุ่มเพื่อควบคุมการไหลเวียนของอากาศ) เมื่อมันร้อนเกินไปฉันต้องปรับลูกบิดตัวแรกเพื่อลดอุณหภูมิและอาจทำให้กระแสลมเปลี่ยนไป) และรองข้อถ้ามันเย็นเกินไป นี่คืองานที่จำเป็น! ฉันต้องจัดการลูกบิดเอง ในรถคันที่สอง (ใหม่กว่า) ของฉันฉันสามารถตั้ง / ประกาศอุณหภูมิได้ ซึ่งหมายความว่าฉันไม่ต้องซอกับลูกบิดเพื่อปรับอุณหภูมิรถของฉันรู้ว่าฉันประกาศ / ตั้งค่าไว้ที่ 72 ° F และรถของฉันจะทำงานที่จำเป็นเพื่อไปยังสถานะนั้น

การตอบสนองจะเหมือนกันคุณประกาศมาร์กอัป / เทมเพลตและสถิติจากนั้น React จะทำงานที่จำเป็นเพื่อให้ DOM ซิงค์กับแอปของคุณ

<button onClick={activateTeleporter}>Activate Teleporter</button>

แทนที่จะใช้.addEventListener()เพื่อตั้งค่าการจัดการเหตุการณ์เราประกาศสิ่งที่เราต้องการ เมื่อคลิกปุ่มมันจะเรียกใช้activateTeleporterฟังก์ชัน


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