سؤال

لقد كنت أبحث عن الويب أبحث عن تعريف للبرمجة التصريفية والضرورية التي ستلقي بعض الضوء بالنسبة لي. ومع ذلك ، فإن اللغة المستخدمة في بعض الموارد التي وجدتها شاقة - على سبيل المثال في ويكيبيديا. هل لدى أي شخص مثال حقيقي على أنه يمكن أن يظهر لي أنه قد يجلب بعض المنظور لهذا الموضوع (ربما في C#)؟

هل كانت مفيدة؟

المحلول

مثال رائع 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);

هنا ، نقول "أعطنا كل شيء حيث يكون الأمر غريبًا" ، وليس "خطوة من خلال المجموعة. تحقق من هذا العنصر ، إذا كان الأمر غريبًا ، أضفه إلى مجموعة النتائج."

في كثير من الحالات ، سيكون التعليمات البرمجية مزيجًا من كلا التصميمين أيضًا ، لذلك ليس بالأبيض والأسود دائمًا.

نصائح أخرى

البرمجة التصريبية عندما تقول ماذا او ما تريد ، واللغة الضرورية عندما تقول كيف للحصول على ما تريد.

مثال بسيط في بيثون:

# 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 أن هذا هو الوقت المثالي لاستخدام جميع النوى الثمانية للبحث المتوازي السريع. أنت, ، كمبرمج ، لا يهتم بأي من هذه الشروط ، وليس عليك كتابة التعليمات البرمجية الخاصة بك للتعامل مع أي حالة خاصة بهذه الطريقة.

التصريح مقابل الضرورة

أ نموذج البرمجة هو نمط أساسي لبرمجة الكمبيوتر. هناك أربعة نماذج رئيسية: حتمية ، تعليمية ، وظيفية (والتي تعتبر مجموعة فرعية من النموذج التعريفي) والموجهة نحو الكائن.

برمجة التصريح : هو نموذج البرمجة يعبر عن منطق الحساب (ماذا يفعل) دون وصف تدفق التحكم (كيف). تشمل بعض الأمثلة المعروفة للغات المحددة للمجال التعريفي (DSLs) CSS ، والتعبيرات العادية ، ومجموعة فرعية من SQL (تحديد الاستعلامات ، على سبيل المثال) العديد من لغات الترميز مثل 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 ستوفر النتيجة المطلوبة.

سأضيف مثالًا آخر نادراً ما يظهر في مناقشة البرمجة التعريفية/الضرورية: واجهة المستخدم!

في C#، يمكنك بناء واجهة مستخدم باستخدام تقنيات مختلفة.

في النهاية الضرورية ، يمكنك استخدام DirectX أو OpenGL لرسم الأزرار ، ومربعات الاختيار ، وما إلى ذلك ... خطًا (أو حقًا ، مثلث المثلث). الأمر متروك لك أن تقول كيفية رسم واجهة المستخدم.

في النهاية التعريفية ، لديك WPF. أنت تكتب بشكل أساسي بعض XML (نعم ، نعم ، "XAML" من الناحية الفنية) والإطار يعمل من أجلك. أنت تقول كيف تبدو واجهة المستخدم. الأمر متروك للنظام لمعرفة كيفية القيام بذلك.

على أي حال ، مجرد شيء آخر للتفكير فيه. لمجرد أن لغة واحدة تعليمية أو لا تعني أنها لا تحتوي على ميزات معينة من الآخر.

وأيضًا ، فإن إحدى فائدة البرمجة التصريحية هي أن الغرض عادة ما يكون أكثر فاعلية من قراءة الكود بينما يمنحك الضرورة السيطرة الدقيقة على التنفيذ.

جوهر كل شيء:

التصريح -> what تريد القيام به

حتمية -> how تريد القيام بذلك

جميع الإجابات المذكورة أعلاه وغيرها من المشاركات عبر الإنترنت تذكر ما يلي:

  • مع تصريحي البرمجة ، تكتب رمزًا يصف ما تريد ، ولكن ليس بالضرورة كيفية الحصول عليه
  • يجب أن تفضل البرمجة التعريفية على البرمجة الضرورية

ما لم يخبروه هو كيفية تحقيق ذلك. لكي يكون جزء من البرنامج أكثر تصريحًا ، يجب أن تكون الأجزاء الأخرى توفير التجريد لإخفاء تفاصيل التنفيذ (وهي صيغة الامر الرموز).

  • على سبيل المثال ، LINQ أكثر إعلانًا من الحلقات (ل ، بينما ، إلخ) ، على سبيل المثال ، يمكنك استخدامك list.Where() للحصول على قائمة ترشيح جديدة. لكي ينجح هذا ، قامت Microsoft بكل الرفع الثقيل خلف تجريد LINQ.

في الواقع ، فإن أحد الأسباب التي تجعل البرمجة الوظيفية والمكتبات الوظيفية أكثر تصريحًا لأنها استخلصت الحلقات وإبداعات القائمة ، وإخفاء جميع تفاصيل التنفيذ (على الأرجح الرموز الضرورية مع الحلقات) خلف مكان الحادث.

في أي برنامج ، سيكون لديك دائمًا رموز حتمية ومصورية ، ما يجب أن تهدف إليه هو إخفاء الجميع صيغة الامر الرموز وراء التجريدات ، بحيث يمكن لأجزاء أخرى من البرنامج استخدامها تعريفيا.

أخيرًا ، على الرغم من أن البرمجة الوظيفية و 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();

أحببت شرحًا من دورة كامبريدج + أمثلةهم:

  • تصريحي - حدد ماذا او ما لكى يفعل، كيف لا للقيام بذلك
    • على سبيل المثال: يصف HTML ما يجب أن يظهر على صفحة ويب ، وليس كيفية رسمها على الشاشة
  • صيغة الامر - حدد كلاهما ماذا او ما و كيف
    • int x; - ماذا (التصريحي)
    • x=x+1; - كيف

تتطلب البرمجة الضرورية للمطورين تحديد خطوة بخطوة كيفية تنفيذ التعليمات البرمجية. لإعطاء الاتجاهات بطريقة حتمية ، تقول: "انتقل إلى الشارع الأول ، انعطف يسارًا إلى مين ، وقم بقيادة كتلتين ، واتجه يمينًا إلى القيقب ، وتوقف عند المنزل الثالث على اليسار." قد تبدو النسخة التصريحية شيئًا من هذا القبيل: "القيادة إلى منزل Sue". يقول المرء كيف يفعل شيئًا ؛ الآخر يقول ما يجب القيام به.

الأسلوب التعريفي له مزايزتان على الأسلوب الحتمي:

  • لا يجبر المسافر على حفظ مجموعة طويلة من التعليمات.
  • يسمح للمسافر بتحسين المسار عندما يكون ذلك ممكنًا.

Calvert ، C Kulkarni ، D (2009). LINQ الأساسي. أديسون ويسلي. 48.

الفرق له علاقة في الغالب بالمستوى الكلي للتجريد. مع التصريح ، في مرحلة ما ، أنت بعيد جدًا عن الخطوات الفردية لدرجة أن البرنامج لديه الكثير من خط العرض فيما يتعلق بكيفية الحصول على النتيجة.


يمكنك إلقاء نظرة على كل قطعة من التعليمات على أنها تسقط في مكان ما في سلسلة متصلة:

درجة التجريد:

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

مثال على العالم الحقيقي:

  1. أمين المكتبة ، يرجى التحقق من نسخة من Moby Dick. (أمين المكتبة ، حسب تقديرهم يختار أفضل طريقة لأداء الطلب)

مثال على العالم الحقيقي:

  1. اذهب إلى المكتبة
  2. ابحث عن نظام تنظيم الكتب (كتالوج البطاقات - المدرسة القديمة)
  3. البحث عن كيفية استخدام كتالوجات البطاقات (لقد نسيت أيضًا ، صحيحًا)
  4. اكتشف كيف يتم تصنيف الأرفف وتنظيمها.
  5. اكتشف كيف يتم تنظيم الكتب على الرف.
  6. موقع دفتر المرجع المتقاطع من كتالوج البطاقات مع نظام التنظيم للعثور على كتاب مذكر.
  7. خذ كتابًا إلى نظام تسجيل المغادرة.
  8. تحقق من الكتاب.

البرمجة الضرورية هي إخبار الكمبيوتر بشكل صريح بما يجب القيام به ، وكيفية القيام بذلك ، مثل تحديد الطلب وما شابه

ج#:

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

التصريح هو عندما تخبر الكمبيوتر بما يجب القيام به ، ولكن ليس في الحقيقة كيفية القيام بذلك. 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}
     )

(مثال من ويكيبيديا لينك)

في علوم الكمبيوتر ، تعد البرمجة التعريفية نموذجًا للبرمجة يعبر عن منطق الحساب دون وصف تدفق التحكم.

من http://en.wikipedia.org/wiki/declarative_programming

باختصار ، تكون اللغة التعريفية أبسط لأنها تفتقر إلى تعقيد تدفق التحكم (الحلقات ، إذا كانت العبارات ، إلخ)

المقارنة الجيدة هي نموذج ASP.NET 'code-behind'. لديك ملفات. aspx "، ثم ملفات رمز ASPX.CS الضرورية. غالبًا ما أجد أنه إذا كان بإمكاني فعل كل ما أحتاجه في النصف التعريفي من النص ، فيمكنه الكثير من الناس متابعة ما يجري.

سرقة من فيليب روبرتس هنا:

  • تخبر البرمجة الضرورية الجهاز كيفية القيام بشيء ما (مما يؤدي إلى ما تريد أن يحدث)
  • تخبر البرمجة التصريبية الجهاز بما ترغب في حدوثه (ويكتشف الكمبيوتر كيفية القيام بذلك)

مثالان:

1. مضاعفة جميع الأرقام في صفيف

ضرورية:

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]

بشكل إعلاني:

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. جمع جميع العناصر في القائمة

ضرورية

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

تعريفيا

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

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

لاحظ كيف تنطوي الأمثلة الضرورية على إنشاء متغير جديد ، وتحوره ، وإرجاع هذه القيمة الجديدة (أي كيفية جعل شيء ما يحدث) ، في حين أن الأمثلة التصريحية يتم تنفيذها على إدخال معين وإرجاع القيمة الجديدة بناءً على الإدخال الأولي (أي ، ما نريد أن يحدث).

البرمجة الضرورية
لغة برمجة تتطلب انضباط البرمجة مثل C/C ++ و Java و Cobol و Fortran و Perl و JavaScript. يجب على المبرمجين الذين يكتبون بمثل هذه اللغات تطوير ترتيب مناسب من الإجراءات من أجل حل المشكلة ، استنادًا إلى معرفة معالجة البيانات وبرامجها.

برمجة التصريح
لغة الكمبيوتر التي لا تتطلب كتابة منطق البرمجة التقليدية ؛ يركز المستخدمون على تحديد الإدخال والمخرجات بدلاً من خطوات البرنامج المطلوبة بلغة البرمجة الإجرائية مثل C ++ أو Java.

أمثلة البرمجة التعريفية هي CSS ، HTML ، XML ، XSLT ، Regx.

فقط لإضافة مثال آخر من حيث تطوير تطبيقات الهاتف المحمول. في iOS و Android ، لدينا بناة الواجهة ، حيث يمكننا تحديد واجهة المستخدم للتطبيقات.

واجهة المستخدم المرسومة باستخدام هذه البناة هي تصريحية بطبيعتها ، حيث نقوم بسحب المكونات وإسقاطها. يحدث Draeing الفعلي أسفله ويؤديه الإطار والنظام.

ولكن يمكننا أيضًا رسم المكونات بأكملها في الكود ، وهذا أمر ضروري في الطبيعة.

أيضًا ، تركز بعض اللغات الجديدة مثل Angular JS على تصميم واجهة المستخدم بشكل إعلاني وقد نرى الكثير من اللغات الأخرى التي تقدم نفس الدعم. مثل Java لا تملك أي طريقة إعلانية جيدة لرسم تطبيقات سطح المكتب الأصلية في Java Swing أو Java FX ولكن في المستقبل القريب قد يكونون قد.

البرنامج التصريحي هو مجرد بيانات لبعض التنفيذ الحتمي/VM "العالمي".

الإيجابيات: تحديد بيانات فقط ، بتنسيق بعض المتشددين (والتحقق) ، هو أبسط وأقل عرضة للخطأ من تحديد البديل لبعض الخوارزمية الضرورية مباشرة. بعض المواصفات المعقدة لا يمكن كتابتها مباشرة ، فقط في شكل DSL. أفضل و Freq المستخدمة في هياكل بيانات DSLS هي مجموعات وجداول. لأنه ليس لديك تبعيات بين العناصر/الصفوف. وعندما لم تكن تبعية لديك حرية في تعديل وسهولة الدعم. (قارن على سبيل المثال الوحدات النمطية ذات الفصول الدراسية - مع الوحدات النمطية سعيدة ومع فصول ، لديك مشكلة فئة قاعدة هشة) جميع سلع الإعلان و DSL تتبع فورًا من فوائد هياكل البيانات هذه (الجداول والمجموعات). بالإضافة إلى ذلك-يمكنك تغيير تنفيذ اللغة التعريفية VM ، إذا كان DSL أكثر أو أقل مجردة (مصممة بشكل جيد). جعل التنفيذ الموازي ، على سبيل المثال. أو تنقله إلى نظام تشغيل آخر وما إلى ذلك. كل واجهات أو بروتوكولات عزلية جيدة تحددها تمنحك هذه الحرية وسهولة الدعم.

MILESES: تخمين الصحيح. قد يكون تنفيذ خوارزمية/VM عام (ومعلمة بواسطة DSL) أبطأ و/أو ذاكرة جائعة من طائرة محددة. في بعض الحالات. إذا كانت هذه الحالات نادرة - فما عليك سوى نسيانها ، فليكن بطيئًا. إذا كان الأمر تردد - يمكنك دائمًا تمديد DSL/VM لهذه الحالة. في مكان ما يتباطأ جميع الحالات الأخرى ، بالتأكيد ...

PS Frameworks هو في منتصف الطريق بين DSL و Leargerative. وبما أن جميع حلول منتصف الطريق ... فهي تجمع بين العلوم ، وليس الفوائد. إنها ليست آمنة للغاية وليست سريعة :) انظر إلى Haskell من جاك كل شيء-إنها في منتصف الطريق بين ML Simple Simple و Metaprog Prolog المرن و ... يا له من وحش. يمكنك أن تنظر إلى Prolog باعتبارها هاسكل مع وظائف/مسببات منطقية فقط. ومدى بساطة مرونتها ضد هاسكل ...

أنا فقط أتساءل لماذا لم يذكر أحد فئات السمات كأداة برمجة إعلانية في C#. لقد تحدثت الإجابة الشائعة لهذه الصفحة عن LINQ كأداة برمجة إعلانية.

وفقا لويكيبيديا

تتضمن اللغات التعريفية الشائعة لغات الاستعلام عن قاعدة البيانات (على سبيل المثال ، SQL ، Xquery) ، والتعبيرات العادية ، والبرمجة المنطقية ، والبرمجة الوظيفية ، وأنظمة إدارة التكوين.

لذا فإن LINQ ، باعتبارها بناء جملة وظيفية ، هي بالتأكيد طريقة إعلانية ، ولكن فئات السمات في C#، كأداة تكوين ، هي تصريحية أيضًا. فيما يلي نقطة انطلاق جيدة لقراءة المزيد عنها: نظرة عامة سريعة على برمجة السمات C#

من فهمي ، كلا المصطلحين لهما جذور في الفلسفة ، هناك أنواع معلنة وضرورية من المعرفة. المعرفة التعريفية هي تأكيدات الحقيقة ، وبيانات حقيقة مثل بديهيات الرياضيات. يخبرك بشيء. يخبرك الحتمية ، أو المعرفة الإجرائية ، خطوة بخطوة كيفية الوصول إلى شيء ما. هذا ما هو تعريف الخوارزمية بشكل أساسي. إذا أردت ، قارن لغة برمجة الكمبيوتر باللغة الإنجليزية. الجمل التعريفية ذكر شيء. مثال ممل ، ولكن إليك طريقة إعلانية لعرض ما إذا كان رقمين يساويان بعضهما البعض ، في جافا:

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);
}

في الأساس ، المعرفة التعريفية يتخطى بعض العناصر لتشكيل طبقة من التجريد على تلك العناصر. البرمجة التعريفية تفعل الشيء نفسه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top