ความแตกต่างระหว่างการเขียนโปรแกรมที่เปิดเผยและจำเป็นคืออะไร? [ปิด]


541

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


3
ความจำเป็นไปที่ร้านอาหารและสั่งซื้อ 6oz สเต็ก (สุกที่หายาก), มันฝรั่งทอด (พร้อมซอสมะเขือเทศ), สลัดข้าง (พร้อมฟาร์มปศุสัตว์) และโค้ก (ไม่มีน้ำแข็ง) พนักงานเสิร์ฟมอบสิ่งที่เขาขออย่างแน่นอนและเขาคิดเงิน $ 14.50 ในขณะที่ปฏิญญาไปที่ร้านอาหารและบอกบริกรว่าเขาต้องการเพียงแค่จ่ายเงินประมาณ 12 ดอลล่าร์สำหรับมื้อเย็น บริกรกลับมาพร้อมกับ 6oz สเต็ก (อาหารกลาง), ด้านข้างของมันบด, บร็อคโคลี่นึ่ง, อาหารเย็นและน้ำหนึ่งแก้ว เขาคิดเงิน $ 11.99
cs_pupil

คำตอบ:


786

ตัวอย่าง C # ที่ยอดเยี่ยมของการเขียนโปรแกรมที่เปิดเผยและจำเป็นคือ LINQ

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

ตัวอย่างเช่นเรามาเริ่มด้วยการสะสมนี้แล้วเลือกตัวเลขคี่:

List<int> collection = new List<int> { 1, 2, 3, 4, 5 };

ด้วยการเขียนโปรแกรมที่จำเป็นเราจะทำสิ่งนี้และตัดสินใจในสิ่งที่เราต้องการ:

List<int> results = new List<int>();
foreach(var num in collection)
{
    if (num % 2 != 0)
          results.Add(num);
}

ที่นี่เรากำลังพูดว่า:

  1. สร้างการรวบรวมผลลัพธ์
  2. ผ่านแต่ละหมายเลขในคอลเล็กชัน
  3. ตรวจสอบหมายเลขถ้าเป็นเลขคู่ให้เพิ่มลงในผลลัพธ์

ในทางกลับกันการเขียนโปรแกรมแบบประกาศคุณเขียนโค้ดที่อธิบายสิ่งที่คุณต้องการ แต่ไม่จำเป็นว่าจะต้องทำอย่างไร (ประกาศผลที่คุณต้องการ แต่ไม่ใช่ขั้นตอน):

var results = collection.Where( num => num % 2 != 0);

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

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


8
+1 อย่างไรก็ตามก่อนอื่นคุณพูดถึง LINQ แต่มีตัวอย่างอะไรบ้างที่เกี่ยวข้อง
Zano

15
collection.Where ใช้วิธีการขยาย LINQ ที่เปิดเผย มันไม่ได้ใช้คุณสมบัติภาษา C # แต่เป็น API การประกาศ ฉันไม่ต้องการผสมข้อความที่นี่ซึ่งเป็นเหตุผลที่ฉันหลีกเลี่ยงการเพิ่มภาษาที่สร้างขึ้นบนวิธีการที่ประกาศ
Reed Copsey

241
สำหรับฉันแล้วดูเหมือนว่าการเขียนโปรแกรมเชิงประกาศไม่มีอะไรมากไปกว่าเลเยอร์ของนามธรรม
Drazen Bjelovuk

8
นี่เป็นคำตอบที่ดี แต่เป็นการตอบสนองความแตกต่างระหว่างการทำงานที่ไม่บริสุทธิ์และการเขียนโปรแกรมที่จำเป็น collection.Whereไม่ได้ใช้ไวยากรณ์ที่ประกาศให้ Linq - ดูmsdn.microsoft.com/en-us/library/bb397906.aspxสำหรับตัวอย่างfrom item in collection where item%2 != 0 select itemจะเป็นรูปแบบการประกาศ การเรียกใช้ฟังก์ชันไม่ได้เป็นการเขียนโปรแกรมเพื่อการประกาศเนื่องจากฟังก์ชันนั้นอยู่ใน System.Linq namespace
Pete Kirkham

30
@PeteKirkham ไวยากรณ์ที่คุณใช้ไม่ใช่ปัญหา - การประกาศเทียบกับความจำเป็นเป็นสิ่งเพิ่มเติมเกี่ยวกับการประกาศสิ่งที่คุณต้องการให้เกิดขึ้นกับการอธิบายอย่างชัดเจนว่าจะต้องเกิดขึ้นอย่างไร การใช้ไวยากรณ์รวมหรือวิธีส่วนขยายเป็นปัญหาแยกต่างหาก
Reed Copsey

145

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

ตัวอย่างง่ายๆใน Python:

# Declarative
small_nums = [x for x in range(20) if x < 5]

# Imperative
small_nums = []
for i in range(20):
    if i < 5:
        small_nums.append(i)

ตัวอย่างแรกคือการประกาศเนื่องจากเราไม่ได้ระบุ "รายละเอียดการใช้งาน" ใด ๆ ของการสร้างรายการ

ในการผูกตัวอย่าง C # โดยทั่วไปแล้วใช้ LINQ ผลลัพธ์ในรูปแบบการประกาศเพราะคุณไม่ได้บอกวิธีการได้รับสิ่งที่คุณต้องการ; คุณกำลังพูดในสิ่งที่คุณต้องการเท่านั้น คุณสามารถพูดแบบเดียวกันเกี่ยวกับ SQL

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

SELECT score FROM games WHERE id < 100;

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


30
Python นั้นไม่ใช่การประกาศ
Juanjo Conti

18
@Juanjo: มันเป็นงานศิลปะ
missingfaktor

3
คำแถลงแรกในที่นี้มีการเปิดเผยอะไรมากกว่าข้อที่สอง?
zenna

17
การเห็นด้วยกับ Juanjo และ zenna - โครงสร้างลูปไม่ได้แปลงเป็นโปรแกรมที่มีการประกาศได้อย่างน่าอัศจรรย์
เฟลิกซ์แฟรงก์

11
ไม่เห็นด้วยกับ @FelixFrank และเอนตัวไปที่คำสั่ง "ตัวหนา" ของ @ missingfaktor วิธีดั้งเดิมที่เปิดเผยอย่างเต็มที่ในการทำเช่นนี้filter(lambda x: x < 5, range(20))เป็นเพียงการปรับโครงสร้างอีกครั้งในสัญกรณ์ที่สั้นกว่า สิ่งนี้ไม่ได้มีความหมายแตกต่างจากนิพจน์ความเข้าใจในรายการ (ซึ่งมีส่วน "แผนที่" และ "ตัวกรอง" ที่ชัดเจน) ซึ่งสร้างขึ้น (ดูpep 202 ) ด้วยความตั้งใจที่ชัดเจนในการสร้างสัญ และความเข้าใจในรายการนี้จะมีความชัดเจนมากขึ้น / เป็นสำนวนในกรณีนี้
yoniLavi

100

Declarative vs. Imperative

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

Declarative Programming : เป็นกระบวนทัศน์การเขียนโปรแกรมที่แสดงออกถึงตรรกะของการคำนวณ (What do) โดยไม่อธิบายถึงโฟลว์การควบคุม (How do) ตัวอย่างที่รู้จักกันดีของภาษาเฉพาะโดเมนที่ประกาศ (DSL) รวมถึง CSS, นิพจน์ทั่วไปและชุดย่อยของ SQL (ตัวอย่างคิวรี SELECT) ภาษามาร์กอัปหลายภาษาเช่น HTML, MXML, XAML, XSLT ... มักจะเป็นการประกาศ การเขียนโปรแกรมเชิงประกาศพยายามทำให้ความแตกต่างระหว่างโปรแกรมเป็นชุดของคำสั่งและโปรแกรมเป็นการยืนยันเกี่ยวกับคำตอบที่ต้องการ

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

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

ตัวอย่างการเขียนโปรแกรมที่จำเป็นในMSDNต่อไปนี้วนผ่านตัวเลข 1 ถึง 10 และค้นหาตัวเลขคู่

var numbersOneThroughTen = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//With imperative programming, we'd step through this, and decide what we want:
var evenNumbers = new List<int>();
foreach (var number in numbersOneThroughTen)
{    if (number % 2 == 0)
    {
        evenNumbers.Add(number);
    }
}
//The following code uses declarative programming to accomplish the same thing.
// Here, we're saying "Give us everything where it's odd"
var evenNumbers = numbersOneThroughTen.Select(number => number % 2 == 0);

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


7
คุณสามารถเพิ่มคำอธิบายสำหรับเชิงวัตถุได้หรือไม่?
mbigras

1
ตัวอย่างที่ดี: tylermcginnis.com/imperative-vs-declarative-programming
user3245268

54

คำตอบข้างต้นทั้งหมดและโพสต์ออนไลน์อื่น ๆ พูดถึงดังต่อไปนี้:

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

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

  • ตัวอย่างเช่น LINQ มีการประกาศมากกว่าลูป (สำหรับในขณะที่ ฯลฯ ) เช่นคุณสามารถใช้list.Where()เพื่อรับรายการที่กรองใหม่ เพื่อให้สามารถใช้งานได้ Microsoft ได้ทำทุกวิถีทางที่จะยกระดับการทำงานของ LINQ

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

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

สุดท้ายแม้ว่าการโปรแกรมเชิงฟังก์ชันและ LINQ สามารถทำให้โปรแกรมของคุณมีความชัดเจนมากขึ้น ตัวอย่างเช่น:

// JavaScript example

// Least declarative
const bestProducts = [];
for(let i = 0; i < products.length; i++) {
    let product = products[i];
    if (product.rating >= 5 && product.price < 100) {
        bestProducts.push(product);
    }
}


// More declarative
const bestProducts = products.filter(function(product) {
    return product.rating >= 5 && product.price < 100;
});

// Most declarative, implementation details are hidden in a function
const bestProducts = getBestProducts();

ป.ล.สุดยอดของการเขียนโปรแกรมเชิงประกาศคือการคิดค้นภาษาเฉพาะโดเมนใหม่ (DSL):

  1. การค้นหาสตริง : นิพจน์ปกติแทนรหัสที่กำหนดเอง
  2. React.js : JSX แทนการจัดการ DOM โดยตรง
  3. AWS CloudFormation : YAML แทนที่จะเป็น CLI
  4. ฐานข้อมูลเชิงสัมพันธ์ : SQL แทน API อ่าน - เขียนที่เก่ากว่าเช่น ISAM หรือ VSAM

มีตัวอย่างที่ดีมากมายของการเขียนโปรแกรมที่เปิดเผย: ทำปฏิกิริยา , CloudFormation , Terraform
engineforce

ดังนั้นการเขียนโปรแกรม "declarative" หมายถึงการย้ายรหัสที่ทำงานไปยังฟังก์ชั่น?
Guillaume F.

@GuillaumeF มันเกี่ยวกับการสร้างนามธรรมเฉพาะโดเมน เช่น - ธนาคาร: คุณควรสร้างฟังก์ชั่นเช่นdebit, depositฯลฯ แทนการทำซ้ำรหัส imparativeaccount.balance += depositAmount
engineforce

44

ฉันจะเพิ่มอีกตัวอย่างที่ไม่ค่อยปรากฏขึ้นในการอภิปรายการเขียนโปรแกรมการประกาศ / ความจำเป็น: ส่วนต่อประสานผู้ใช้!

ใน C # คุณสามารถสร้าง UI โดยใช้เทคโนโลยีที่หลากหลาย

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

ในตอนท้ายของการประกาศคุณมี WPF โดยทั่วไปคุณเขียน XML (ใช่, ใช่, "XAML" ทางเทคนิค) และกรอบการทำงานนั้นเหมาะกับคุณ คุณพูดว่าส่วนต่อประสานผู้ใช้เป็นอย่างไร มันขึ้นอยู่กับระบบที่จะคิดออกว่าจะทำอย่างไร

อย่างไรก็ตามมีอีกเรื่องที่ต้องคิด เพียงเพราะภาษาหนึ่งมีการประกาศหรือคำสั่งไม่ได้หมายความว่ามันไม่มีคุณสมบัติบางอย่างของอื่น ๆ

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

ส่วนสำคัญของมันทั้งหมด:

Declarative -> ที่whatคุณต้องการ

จำเป็น -> howคุณต้องการทำมัน


27

ฉันชอบคำอธิบายจากหลักสูตร Cambridge + ตัวอย่างของพวกเขา:

  • Declarative - ระบุสิ่งที่ต้องทำไม่ใช่วิธีการ
    • เช่น HTML อธิบายสิ่งที่ควรปรากฏบนหน้าเว็บไม่ใช่วิธีวาดบนหน้าจอ
  • จำเป็น - ระบุทั้งอะไรและอย่างไร
    • int x; - อะไร (ประกาศ)
    • x=x+1; - อย่างไร

"ไม่ควรวาดลงบนหน้าจอ" ... หมายความว่าCSSเป็นสิ่งที่จำเป็นหรือไม่
Chef_Code

11
ฉบับนอกจากนี้ยังสามารถได้รับการพิจารณาเปิดเผยเพราะคุณเพียงแค่พูดในสิ่งที่คุณต้องการ - "นี้ทำให้ฟ้าเซลล์ชายแดน" ลองนึกภาพว่าคุณต้องการวาดเส้นขอบเดียวกันด้วยวิธีการที่จำเป็น (เช่น: JavaScript) จากนั้นคุณต้องพูดว่า"ไปที่จุด (x1, y1), ลากเส้นสีน้ำเงินระหว่างจุดนี้และ (x2, y1), ลากเส้นสีน้ำเงินจาก (x2, y1) ถึง (x2, y2), วาดเส้นสีน้ำเงิน จาก (x2, y2) ถึง (x1, y2) วาดเส้นสีฟ้าจาก (x1, y2) ถึง (x1, y1)"
ROMANIA_engineer

@ROMANIA_engineer ฉันจะหาหลักสูตรเคมบริดจ์แบบนั้นได้ที่ไหน
ทีมทดสอบ

@testteam ค้นหา "cl.cam.ac.uk Teaching ooprog" ใน Google คุณสามารถเปลี่ยนปีจาก URL
ROMANIA_engineer

@ROMANIA_engineer เข้าใจแล้วขอบคุณ
ทีมทดสอบ

26

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


คุณสามารถดูการเรียนการสอนทุกชิ้นในลักษณะที่ตกลงมาอย่างต่อเนื่อง

ระดับของสิ่งที่เป็นนามธรรม:

Declarative <<=====|==================>> Imperative

ตัวอย่างการประกาศในโลกแห่งความจริง:

  1. บรรณารักษ์โปรดตรวจสอบสำเนา Moby Dick (บรรณารักษ์ตามดุลยพินิจของพวกเขาเลือกวิธีที่ดีที่สุดสำหรับการดำเนินการตามคำขอ)

ตัวอย่างโลกแห่งความจริงที่จำเป็น:

  1. ไปที่ห้องสมุด
  2. ค้นหาระบบการจองหนังสือ (แคตตาล็อกการ์ด - โรงเรียนเก่า)
  3. ศึกษาวิธีการใช้แคตตาล็อกบัตร (คุณลืมด้วยใช่ไหม)
  4. กำหนดวิธีการติดป้ายและจัดระเบียบชั้นวาง
  5. กำหนดวิธีจัดระเบียบหนังสือบนชั้นวาง
  6. การอ้างอิงแบบข้ามตำแหน่งจากแคตตาล็อกการ์ดพร้อมระบบองค์กรเพื่อค้นหาหนังสือดังกล่าว
  7. จองเพื่อเช็คเอาท์ระบบ
  8. ตรวจสอบหนังสือ

นี่ไม่ใช่สิ่งที่เป็นนามธรรมเกี่ยวกับสิ่งที่เป็นนามธรรมมากกว่าสิ่งที่บอกให้รู้ คุณยังคงแนะนำให้บรรณารักษ์นำหนังสือมาด้วย
kamathln

คำตอบที่อัปเดตแล้วจะมีความสมบูรณ์มากขึ้นและรวมถึงส่วนนี้ในโซลูชัน
Lucent Fox

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

24

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

สไตล์การประกาศมีสองข้อได้เปรียบเหนือสไตล์ที่จำเป็น:

  • มันไม่ได้บังคับให้นักท่องจำจดจำชุดคำสั่งที่ยาว
  • ช่วยให้นักเดินทางปรับเส้นทางให้เหมาะสมเมื่อทำได้

Calvert, C Kulkarni, D (2009) LINQ ที่สำคัญ แอดดิสันเวสลีย์ 48


11

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

ค#:

for (int i = 0; i < 10; i++)
{
    System.Console.WriteLine("Hello World!");
}

Declarative คือเมื่อคุณบอกคอมพิวเตอร์ว่าจะต้องทำอะไร แต่ไม่ใช่ว่าจะทำอย่างไร Datalog / Prolog เป็นภาษาแรกที่คำนึงถึงในเรื่องนี้ โดยทั่วไปทุกอย่างเป็นสิ่งที่เปิดเผย คุณไม่สามารถรับประกันการสั่งซื้อได้

C # เป็นภาษาการเขียนโปรแกรมที่จำเป็นยิ่งขึ้น แต่คุณสมบัติบางอย่างของ C # นั้นมีความชัดเจนมากกว่าเช่น Linq

dynamic foo = from c in someCollection
           let x = someValue * 2
           where c.SomeProperty < x
           select new {c.SomeProperty, c.OtherProperty};

สิ่งเดียวกันสามารถเขียนได้อย่างไม่จำเป็น:

dynamic foo = SomeCollection.Where
     (
          c => c.SomeProperty < (SomeValue * 2)
     )
     .Select
     (
          c => new {c.SomeProperty, c.OtherProperty}
     )

(ตัวอย่างจากวิกิพีเดีย Linq)


2
คุณมีการพิมพ์ผิด: คำสั่ง linq เป็นแบบประกาศ, ไม่จำเป็น (คุณมี "คุณสมบัติ C # มีความจำเป็นมากกว่าเช่น Linq" ควรอ่านข้อความ
กก Copsey

แก้ไขแล้ว (บางเวลาก่อนหน้า)
แมคเคย์

8

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

จากhttp://en.wikipedia.org/wiki/Declarative_programming

โดยสรุปภาษาที่ประกาศนั้นง่ายกว่าเพราะไม่มีความซับซ้อนของโฟลว์การควบคุม (ลูปหากคำสั่ง ฯลฯ )

การเปรียบเทียบที่ดีคือรูปแบบ 'behind รหัส' ของ ASP.Net คุณมีไฟล์ '.ASPX' ที่ประกาศได้และจากนั้นไฟล์รหัส 'ASPX.CS' ที่จำเป็น ฉันมักจะพบว่าถ้าฉันสามารถทำทุกอย่างที่ฉันต้องการในช่วงครึ่งแรกของสคริปต์ผู้คนจำนวนมากสามารถติดตามสิ่งที่กำลังทำอยู่


7

ขโมยจากPhilip Roberts ที่นี่ :

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

สองตัวอย่าง:

1. การเพิ่มตัวเลขทั้งหมดในอาเรย์

imperatively:

var numbers = [1,2,3,4,5]
var doubled = []

for(var i = 0; i < numbers.length; i++) {
  var newNumber = numbers[i] * 2
  doubled.push(newNumber)
}
console.log(doubled) //=> [2,4,6,8,10]

declaratively:

var numbers = [1,2,3,4,5]

var doubled = numbers.map(function(n) {
  return n * 2
})
console.log(doubled) //=> [2,4,6,8,10]

2. รวมรายการทั้งหมดในรายการ

imperatively

var numbers = [1,2,3,4,5]
var total = 0

for(var i = 0; i < numbers.length; i++) {
  total += numbers[i]
}
console.log(total) //=> 15

declaratively

var numbers = [1,2,3,4,5]

var total = numbers.reduce(function(sum, n) {
  return sum + n
});
console.log(total) //=> 15

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


5
เช่นเดียวกับคำตอบมากมายที่น่าตกใจสำหรับคำถามนี้ตัวอย่างการเขียนโปรแกรม 'แบบประกาศ' ของคุณเป็นตัวอย่างของการเขียนโปรแกรมเชิงฟังก์ชัน ความหมายของ 'map' คือ 'ใช้ฟังก์ชันนี้กับองค์ประกอบของอาร์เรย์ตามลำดับ' คุณไม่อนุญาตให้มีการใช้งานไทม์เวย์ในการดำเนินการ
Pete Kirkham

4

Imperative programming
ภาษาที่ใช้ในการเขียนโปรแกรมจำเป็นต้องมีระเบียบวินัยในการเขียนโปรแกรมเช่น C / C ++, Java, COBOL, FORTRAN, Perl และ JavaScript โปรแกรมเมอร์ที่เขียนในภาษาดังกล่าวจะต้องพัฒนาลำดับของการกระทำที่เหมาะสมเพื่อแก้ปัญหาโดยอาศัยความรู้ในการประมวลผลข้อมูลและการเขียนโปรแกรม

การเขียนโปรแกรมการประกาศ
ภาษาคอมพิวเตอร์ที่ไม่ต้องการการเขียนตรรกะการเขียนโปรแกรมแบบดั้งเดิม ผู้ใช้ให้ความสำคัญกับการกำหนดอินพุทและเอาท์พุทมากกว่าขั้นตอนของโปรแกรมที่ต้องการในภาษาโปรแกรมโพรซีเดอร์เช่น C ++ หรือ Java

ตัวอย่างการเขียนโปรแกรมที่สำแดง ได้แก่ CSS, HTML, XML, XSLT, RegX


2

โปรแกรมการประกาศเป็นเพียงข้อมูลสำหรับการนำไปปฏิบัติ / vm ที่จำเป็นมากขึ้นหรือน้อยลง

ข้อดี: การระบุเพียงแค่ข้อมูลในบางรูปแบบฮาร์ดโค้ด (และตรวจสอบแล้ว) นั้นง่ายกว่าและมีข้อผิดพลาดน้อยกว่าการระบุตัวแปรของอัลกอริธึมบางอย่างที่จำเป็นโดยตรง ข้อกำหนดที่ซับซ้อนบางอย่างไม่สามารถเขียนได้โดยตรงเฉพาะในบางรูปแบบ DSL best และ freq ที่ใช้ในโครงสร้างข้อมูล DSL คือชุดและตาราง เพราะคุณไม่มีการพึ่งพาระหว่างองค์ประกอบ / แถว และเมื่อคุณไม่ได้พึ่งพาคุณมีอิสระในการปรับเปลี่ยนและให้ความช่วยเหลือง่าย (เปรียบเทียบสำหรับตัวอย่างโมดูลที่มีคลาส - กับโมดูลที่คุณมีความสุขและกับคลาสที่คุณมีปัญหาคลาสพื้นฐานที่เปราะบาง) สินค้าทั้งหมดของการเสื่อมสภาพและ DSL ตามมาทันทีจากประโยชน์ของโครงสร้างข้อมูลนั้น (ตารางและชุด) อีกอย่างบวก - คุณสามารถเปลี่ยนการใช้ vm ภาษาที่ประกาศได้ถ้า DSL เป็นนามธรรมมากกว่าหรือน้อยกว่า (ออกแบบมาอย่างดี) ทำให้การใช้งานแบบขนานตัวอย่างเช่น

minuses: คุณเดาถูก ทั่วไป (และแปรตามพารามิเตอร์โดย DSL) การดำเนินการตามขั้นตอนวิธีที่จำเป็น / vm อาจช้าลงและ / หรือหน่วยความจำหิวกว่าหนึ่งที่เฉพาะเจาะจง ในบางกรณี. หากเป็นกรณีที่หายาก - ลืมมันไปเถอะปล่อยให้มันช้า ถ้าเป็นความถี่ - คุณสามารถขยาย DSL / vm สำหรับกรณีนั้นได้เสมอ บางแห่งชะลอตัวลงทุกกรณีแน่นอน ...

PS Frameworks เป็นครึ่งทางระหว่าง DSL และสิ่งจำเป็น และในฐานะที่เป็นวิธีการแก้ปัญหาครึ่งทางทั้งหมด ... พวกเขารวม deficiences ไม่ใช่ผลประโยชน์ พวกเขาไม่ปลอดภัยและไม่เร็วนัก :) ดูที่ jack-of-all-trades haskell - มันอยู่กึ่งกลางระหว่าง ML ง่าย ๆ ที่แข็งแกร่งและ Proapap metaprog ที่ยืดหยุ่นและ ... มันเป็นสัตว์ประหลาดขนาดไหน คุณสามารถดู Prolog เป็น Haskell ด้วยฟังก์ชัน / เพรดิเคตแบบบูลเท่านั้น และความยืดหยุ่นของมันนั้นง่ายเพียงแค่เทียบกับ Haskell ...


2

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

ตามที่ Wikipedia

ภาษาที่ประกาศทั่วไปประกอบด้วยภาษาของคิวรี่ฐานข้อมูล (เช่น SQL, XQuery), นิพจน์ทั่วไป, การเขียนโปรแกรมเชิงตรรกะ, การเขียนโปรแกรมเชิงฟังก์ชันและระบบการจัดการการกำหนดค่า

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


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

2

เพียงเพิ่มตัวอย่างอื่นในแง่ของการพัฒนาแอพมือถือ ใน iOS และ Android เรามี Interface Builders ซึ่งเราสามารถกำหนด UI ของแอพได้

UI ที่วาดโดยใช้ผู้สร้างเหล่านี้เป็นการประกาศตามธรรมชาติซึ่งเราจะลากและวางส่วนประกอบ การวาดภาพที่เกิดขึ้นจริงภายใต้และดำเนินการโดยกรอบและระบบ

แต่เราสามารถวาดส่วนประกอบทั้งหมดในโค้ดและนั่นเป็นสิ่งจำเป็นในธรรมชาติ

นอกจากนี้ภาษาใหม่บางภาษาเช่น Angular JS กำลังมุ่งเน้นไปที่การออกแบบ UIs อย่างชัดเจนและเราอาจเห็นภาษาอื่น ๆ อีกมากมายที่ให้การสนับสนุนเดียวกัน เช่นเดียวกับ Java ไม่มีวิธีการที่ดีในการวาดแอพเดสก์ท็อปดั้งเดิมใน Java swing หรือ Java FX แต่ในอนาคตอันใกล้พวกเขาอาจทำได้


Java ไม่ใช่คำย่อ BTW
Mordechai

1

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

public static void main(String[] args)
{
    System.out.print("4 = 4.");
}

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

private static Scanner input;    

public static void main(String[] args) 
{
    input = new Scanner(System.in);
    System.out.println();
    System.out.print("Enter an integer value for x: ");
    int x = input.nextInt();
    System.out.print("Enter an integer value for y: ");        
    int y = input.nextInt();

    System.out.println();
    System.out.printf("%d == %d? %s\n", x, y, x == y);
}

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

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