聲明式和命令式編程_命令式與聲明式編程


聲明式更適合程序員的編程思路,而命令式卻是我們實際開發中一直在寫的,要學會在實際中多用聲明式編程。

 

聲明式和命令式編程

At this point you’ve undoubtedly heard about imperative programming vs declarative programming. You might have even searched for what those terms actually mean.

至此,您無疑已經聽說了命令式編程與聲明式編程。 您甚至可能已經搜索了這些術語的實際含義。

Sadly, you probably encountered a definition similar to this, “You know, imperative programming is like “how” you do something, and declarative programming is more like “what” you do, or something.”

可悲的是,您可能會遇到類似於以下的定義:“您知道,命令式編程就像“您如何做某事,而聲明式編程更像您在做什么”。

That definition makes perfect sense once you actually know the difference between imperative and declarative — but you don’t, which is why you asked the question in the first place. It’s like trying to answer “What came first, the chicken or the egg?” except everyone seems to think the chicken did, but you don’t even like eggs, and you’re confused.

一旦您真正了解了命令性和聲明性之間的區別,該定義就很有意義了,但是您卻沒有,這就是為什么您首先提出問題的原因。 就像試圖回答“先來的是雞還是雞蛋?” 除了每個人似乎都認為雞肉確實如此,但您甚至不喜歡雞蛋,而且感到困惑。

Combine this frustration with the bastardization of the actual word “declarative” to basically just mean “good” and all of a sudden your imposter syndrome is tap dancing on your confidence, and you realize you don’t even like programming that much.

將此挫敗感與實際的“說明性”一詞的混蛋結合起來,基本上就意味着“  ”,突然間,冒名頂替者綜合征就是在自信的鼓舞下,您意識到自己甚至不喜歡編程。

Don’t worry though, friend. I don’t know what a monad is, so hopefully this post will help you realize that declarative is more than just being “easy to reason about” and “good.”

朋友,請不要擔心。 我不知道什么是monad,所以希望這篇文章可以幫助您認識到聲明式不僅僅是“容易推理”和“好”。

The hard part about this topic is, as Merrick has observed, “It’s one of those things you have an intuition about but can’t seem to explain.”

正如Merrick所觀察到的,有關此主題的困難部分是:“這是您有直覺但似乎無法解釋的事情之一。”

I’ve talked with many developers and what seems to help most is a combination of metaphors with actual code examples. So buckle up cause I’m about to #preach.

我已經與許多開發人員進行了交談,似乎最有幫助的是隱喻與實際代碼示例的結合。 所以請系好安全帶,因為我要#preach。

Let’s go back to the initial definition I made fun of, “Imperative programming is like “How” you do something and declarative programming is more like “What” you do.” There’s actually SOME good information hidden in here. Let’s first see the merit in this definition by taking it out of the context of programming and look at a “real life” example.

讓我們回到我取笑的最初定義:“命令式編程就像您如何做,而聲明式編程更像您在做什么”。 實際上,這里隱藏了一些很好的信息。 首先,讓我們從編程的上下文中了解該定義的優點,並看一個“現實生活”示例。

You decide that you’ve been spending too much time arguing about “JavaScript Fatigue”™ and Reactive Functional Programming, and your husband deserves a nice date. You decide to go to Red Lobster since you’ve been listening to a lot of Beyonce lately. ??. You arrive at Red Lobster, approach the front desk and say…

您決定花太多時間爭論“ JavaScript Fatigue”™和響應式功能編程,而丈夫應該得到一個愉快的約會。 您決定去紅龍蝦,因為您最近一直在聽很多碧昂絲的音樂。 ??。 您到達紅龍蝦,靠近前台說……

An imperative approach (HOW): I see that table located under the Gone Fishin’ sign is empty. My husband and I are going to walk over there and sit down.

一種命令式方法(HOW):我看到位於Gone Fishin'標志下的桌子是空的。 我和我丈夫要去那邊坐下。

A declarative approach (WHAT): Table for two, please.

聲明性方法(WHAT):請為兩個表。

The imperative approach is concerned with HOW you’re actually going to get a seat. You need to list out the steps to be able to show HOW you’re going to get a table. The declarative approach is more concerned with WHAT you want, a table for two.

命令式方法與您實際將如何獲得座位有關。 您需要列出步驟以顯示如何獲取表格。 聲明式方法與您想要的東西有關,一個兩個人的表。

“Ok.” — your brain

“好。” - 你的腦

More metaphors!

更多的隱喻!

I’m going to ask you a question. I want you to think of both an imperative response and a declarative response.

我要問你一個問題。 我希望您同時考慮命令式響應和聲明式響應。

“I’m by Wal-Mart. How do I get to your house from here?”

“我在沃爾瑪。 我怎么從這里到你家?”

An imperative response: Go out of the north exit of the parking lot and take a left. Get on I-15 south until you get to the Bangerter Highway exit. Take a right off the exit like you’re going to Ikea. Go straight and take a right at the first light. Continue through the next light then take your next left. My house is #298.

當務之急是:從停車場北出口出來,向左走。 在I-15州際公路上向南行駛,直到到達Bangerter Highway出口。 就像您要去宜家一樣,在出口處右轉。 一直走,在第一個路口右轉。 繼續穿過下一盞燈,然后左下。 我的房子是#298。

A declarative response: My address is 298 West Immutable Alley, Draper Utah 84020

聲明式答復:我的地址是猶他州德拉珀84020西不可變巷298號

Regardless of how I get to your house, what really matters is the car I drive. Am I going to drive an imperative stick shift car or a declarative automatic car. Enough metaphors?

不管我怎么到你家,真正重要的是我開車。 我要駕駛命令式變速桿汽車還是聲明式自動擋汽車。 足夠的隱喻?

Before we dive into code, it’s important to realize that many declarative approaches have some sort of imperative abstraction layer. Look at all of our examples:

在深入研究代碼之前,必須意識到許多聲明性方法具有某種命令性抽象層。 看我們所有的例子:

The declarative response to the Red Lobster employee is assuming that the Red Lobster employee knows all the imperative steps to get us to the table. Knowing the address assumes you have some sort of GPS that knows the imperative steps of how to get to your house.

對Red Lobster員工的聲明性響應是假設Red Lobster員工了解使我們上桌的所有必要步驟。 知道地址就意味着您擁有某種GPS,該GPS知道如何到達房屋的必要步驟。

An automatic car has some sort of abstraction layer over shifting gears.

自動駕駛汽車在變速桿上有某種抽象層。

That was the realization that really made it click for me, so I’ll repeat it: Many (if not all) declarative approaches have some sort of underlying imperative abstraction.

那就是真正讓我為之點擊的認識,所以我重復一遍:許多(如果不是全部的話)聲明性方法都具有某種底層的命令式抽象。

If that sentence makes sense, you’re doing great!

如果這句話有意義,那么您做得很好!

Now, we’re going to attempt to take the leap from metaphorical happy land to real world code land. To make the leap more graceful, let’s look at some programming “languages” that are inherently declarative versus those which are imperative by nature.

現在,我們將嘗試從隱喻的幸福之地邁向現實世界的代碼之地。 為了使過渡更加順暢,讓我們看一下本質上是聲明性的程序設計“語言”與本質上是命令性的編程“語言”。

Imperative: C, C++, JavaDeclarative: SQL, HTML(Can Be) Mix: JavaScript, C#, Python

命令式:C,C ++,Java聲明式:SQL,HTML(Can Be)組合:JavaScript,C#,Python

Think about your typical SQL or HTML example,

考慮一下您的典型SQL或HTML示例,

SELECT * FROM Users WHERE Country=’Mexico’;
<article> <header> <h1>Declarative Programming</h1> <p>Sprinkle Declarative in your verbiage to sound smart</p> </header></article>

By glancing at both examples, you have a very clear understanding of what is going on. They’re both declarative. They’re concerned with WHAT you want done, rather than HOW you want it done.

通過看兩個例子,您對正在發生的事情有了非常清楚的了解。 它們都是聲明性的。 他們關心的是您要完成的工作,而不是要如何完成。

You’re describing what you’re trying to achieve, without instructing how to do it. The implementation of selecting all of the users who live in Mexico has been abstracted from you. You’re not concerned with how the web browser is parsing your article and displaying it to the screen. Your WHAT is Mexican users and a new header and paragraph on your website.

您正在描述要實現的目標,而沒有指示如何實現。 選擇您居住在墨西哥的所有用戶的實施方法已經抽象。 您不必擔心Web瀏覽器如何解析您的文章並將其顯示在屏幕上。 您是墨西哥用戶 ,您的網站上有一個新的標題段落 。

So far so good. Let’s dive into more practical JavaScript examples.

到目前為止,一切都很好。 讓我們深入研究更實用JavaScript示例。

I want you to pretend you’re now in a technical interview and I’m the interviewer. Open up your console and answer the following questions.

我要你假裝你現在正在接受技術面試,我是面試官。 打開控制台並回答以下問題。

  1. Write a function called double which takes in an array of numbers and returns a new array after doubling every item in that array. double([1,2,3]) -> [2,4,6]

    編寫一個稱為double的函數,該函數接受一個數字數組,並在將該數組中的每個項目加倍后返回一個新數組。 double([1,2,3])-> [ 2,4,6]

  2. Write a function called add which takes in an array and returns the result of adding up every item in the array. add([1,2,3]) ->; 6

    編寫一個名為add的函數,該函數接收一個數組並返回將數組中每個項目相加的結果。 add([1,2,3])-> ; 6

  3. Using jQuery (or vanilla JavaScript), add a click event handler to the element which has an id of “btn”. When clicked, toggle (add or remove) the “highlight” class as well as change the text to “Add Highlight” or “Remove Highlight” depending on the current state of the element.

    使用jQuery(或普通JavaScript),將點擊事件處理程序添加到ID為“ btn”的元素 單擊時,切換(添加或刪除) “突出顯示”類,並根據元素的當前狀態將文本更改為“添加突出顯示”“刪除突出顯示” 。

Let’s look at the most common approaches to these problems, which all happen to also be imperative approaches.

讓我們看一下解決這些問題的最常用方法,所有這些方法碰巧也是必不可少的方法。

function double (arr) { let results = [] for (let i = 0; i < arr.length; i++){ results.push(arr[i] * 2) } return results}

2.

2。

function add (arr) { let result = 0 for (let i = 0; i < arr.length; i++){ result += arr[i] } return result}

3.

3。

$("#btn").click(function() { $(this).toggleClass("highlight") $(this).text() === 'Add Highlight' ? $(this).text('Remove Highlight') : $(this).text('Add Highlight')})

By examining what all three of these imperative examples have in common, we’ll be able to better identify what actually makes them imperative.

通過研究這三個必要命令示例的共同點,我們將能夠更好地確定實際上使它們成為必需命令的原因。

  1. The most obvious commonality is that they’re describing HOW to do something. In each example we’re either explicitly iterating over an array or explicitly laying out steps for how to implement the functionality we want.

    最明顯的共性是他們在描述如何做某事。 在每個示例中,我們要么明確地遍歷數組,要么明確提出有關如何實現所需功能的步驟。

  2. This one might not be as obvious if you’re not used to thinking in the “declarative” or even more specifically “functional” way. In each example we’re mutating some piece of state (If you’re unfamiliar with the term state, it’s basically information about something held in memory— which should sound a lot like variables.) In the first two examples we create a variable called results and then we continually modify it. In the third example we don’t have any variables, but we still have state living in the DOM itself — we then modify that state in the DOM.

    如果您不習慣於以“ 聲明式 ”或更具體地以“ 功能性 ”方式思考,這一點可能並不那么明顯。 在每個示例中,我們都在改變狀態的一部分(如果您不熟悉狀態一詞,它基本上是有關內存中所保存內容的信息,這聽起來很像變量。)在前兩個示例中,我們創建了一個變量,稱為結果,然后我們不斷對其進行修改。 在第三個示例中,我們沒有任何變量,但是狀態仍然存在於DOM本身中-然后在DOM中修改該狀態。

  3. This one is a bit subjective, but to me the code above isn’t very readable. I can’t just glance at the code and understand what’s going on. My brain needs to step through the code just as an interpreter would while also taking into account the context in which the code lives (another negativity of mutable data).

     

    這有點主觀,但是對我來說上面的代碼不是很可讀。 我不能只是看一眼代碼並了解發生了什么。 我的大腦需要像解釋器一樣逐步執行代碼,同時還要考慮代碼所處的上下文(可變數據的另一種否定性)。

All right, enough ?ing on the code. Let’s now take a look at some declarative examples. The goal is to fix all the problems from above. So each example needs to describe WHAT is happening, can’t mutate state, and should be readable at a glance.

好吧,代碼上的代碼足夠了。 現在讓我們看一些聲明性示例。 目標是從上面解決所有問題。 因此,每個示例都需要描述正在發生的事情,不能改變狀態,並且一目了然。

1.

1。

function double (arr) { return arr.map((item) => item * 2)}

2.

2。

function add (arr) { return arr.reduce((prev, current) => prev + current, 0)}

3.

3。

<Btn   onToggleHighlight={this.handleToggleHighlight} highlight={this.state.highlight}> {this.state.buttonText}</Btn>

Much better ?

好多了 ?

Notice that in the first two example we’re leveraging JavaScript’s built in map and reduce methods. This goes back to what we’ve been talking about over and over in this article that most declarative solutions are an abstraction over some imperative implementation.

注意,在前兩個示例中,我們利用了JavaScript的內置mapreduce方法。 這可以回溯到我們在本文中反復討論的內容,即大多數聲明性解決方案都是對某些命令性實現的抽象。

In every example we’re describing WHAT we want to happen rather than HOW (we don’t know HOW map and reduce are implemented, we also don’t care). We’re not mutating any state. All of the mutations are abstracted inside of map and reduce. It’s also more readable (once you get used to map and reduce, of course).

在每個示例中,我們都在描述我們要發生的事情,而不是HOW(我們不知道HOW map和reduce的實現方式,我們也不在乎)。 我們不會改變任何狀態。 所有的變異都在map內部進行了抽象並精簡 。 它也更具可讀性(當然,一旦您習慣了映射reduce )。

Now what about #3? Well I cheated a little bit, and am using React — but note that all three imperative mistakes are still fixed. The real beauty of React is that you can create these declarative user interfaces. By looking at our Btn component, I’m able to easily understand what the UI is going to look like. Another benefit is instead of state living in the DOM, it lives in the React component itself.

現在#3呢? 好吧,我作弊了一點,並且正在使用React –但是請注意,這三個命令性錯誤仍然是固定的。 React的真正魅力在於您可以創建這些聲明性用戶界面。 通過查看我們的Btn組件,我可以輕松了解UI的外觀。 另一個好處是它不存在於DOM中,而是存在於React組件本身中。

Another less-spoken-of benefit to declarative code is that your program can be context-independent. This means that because your code is concerned with what the ultimate goal is — rather than the steps it takes to accomplish that goal — the same code can be used in different programs, and work just fine.

聲明性代碼的另一點好處是您的程序可以獨立於上下文。 這意味着,因為您的代碼關注的是最終目標是什么,而不是實現目標所需要的步驟,所以同一代碼可以在不同的程序中使用,並且工作正常。

Look at all three of our examples above. We can consume both functions and component in any program we want. They’re program agnostic. This is hard to do with imperative code because often times, by definition, imperative code relies on the context of the current state.

查看上面的所有三個示例。 我們可以在任何想要的程序中使用函數和組件。 它們與程序無關。 用命令式代碼很難做到這一點,因為根據定義,命令式代碼通常依賴於當前狀態的上下文。

One thing that I didn’t go too far into is how functional programming is a subset of declarative programming. If you haven’t already, I highly recommend getting more familiar with functional programming techniques in JavaScript. Start with .map, .reduce, .filter and work your way up from there.

我沒有深入探討的一件事是函數式編程是聲明式編程的子集。 如果您還沒有的話,我強烈建議您熟悉JavaScript中的函數式編程技術。 從.map,.reduce,.filter開始,然后從那里開始。

Odds are there isn’t a lower hanging fruit to improve your codebase than making it more functional.

奇怪的是,除了使代碼庫更具功能性之外,沒有什么比它更加有用的了。

With all of this said, one of my favorite things is to find definitions on the internet where the creator of said definition was more concerned with sounding intelligent than providing a useful, consumable definition. Imperative vs declarative has SO many good examples of this. Enjoy!

綜上所述,我最喜歡的事情之一是在互聯網上查找定義,其中,該定義的創建者更關心聽起來智能,而不是提供有用的,可消耗的定義。 命令式與聲明式有很多很好的例子。 請享用!

Declarative programming is “the act of programming in languages that conform to the mental model of the developer rather than the operational model of the machine”.
聲明式編程是“用符合開發人員心理模型而不是機器操作模型的語言進行編程的行為”。
Declarative Programming is programming with declarations, i.e. declarative sentences.
聲明式編程是使用聲明(即聲明性語句)進行編程。
The declarative property is where there can exist only one possible set of statements that can express each specific modular semantic. The imperative property is the dual, where semantics are inconsistent under composition and/or can be expressed with variations of sets of statements.
聲明性屬性是只能存在一組可能表達每個特定模塊化語義的語句的地方。 命令屬性是雙重的,其中語義在組成上是不一致的和/或可以用語句集的變體來表達。

Declarative languages contrast with imperative languages which specify explicit manipulation of the computer’s internal state; or procedural languages which specify an explicit sequence of steps to follow.

聲明性語言與命令性語言形成對比,命令性語言指定了對計算機內部狀態的顯式操作 ; 或指定要遵循的明確步驟順序的程序語言。

In computer science, declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.
在計算機科學中,聲明性編程是一種編程范例,用於表達計算的邏輯而不描述其控制流程。

Originally published at tylermcginnis.com

最初發布於tylermcginnis.com

Follow Tyler McGinnis on Twitter

在Twitter上關注Tyler McGinnis

翻譯自: https://www.freecodecamp.org/news/imperative-vs-declarative-programming-283e96bf8aea/

聲明式和命令式編程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM