Một hoạt động bình thường là gì?


Câu trả lời:


964

Trong điện toán, một hoạt động bình thường là một hoạt động không có tác dụng bổ sung nếu nó được gọi nhiều lần với cùng một tham số đầu vào. Ví dụ: xóa một mục khỏi một tập hợp có thể được coi là một hoạt động bình thường trên tập hợp.

Trong toán học, một phép toán idempotent là một phép toán trong đó f (f (x)) = f (x) . Ví dụ, abs()hàm là idempotent vì abs(abs(x)) = abs(x)cho tất cả x.

Các định nghĩa hơi khác nhau này có thể được đối chiếu bằng cách xem xét x trong định nghĩa toán học đại diện cho trạng thái của một đối tượng và f là một hoạt động có thể làm thay đổi đối tượng đó. Ví dụ, hãy xem xét Pythonsetdiscardphương thức của nó . Các discardphương pháp loại bỏ một phần tử từ một tập, và không có gì nếu nguyên tố này không tồn tại. Vì thế:

my_set.discard(x)

có tác dụng chính xác giống như thực hiện hai thao tác hai lần:

my_set.discard(x)
my_set.discard(x)

Các hoạt động tạm thời thường được sử dụng trong thiết kế các giao thức mạng, trong đó yêu cầu thực hiện thao tác được đảm bảo xảy ra ít nhất một lần, nhưng cũng có thể xảy ra nhiều lần. Nếu hoạt động là idempotent, thì không có hại trong việc thực hiện hoạt động hai lần trở lên.

Xem bài viết Wikipedia về idempotence để biết thêm thông tin.


Câu trả lời trên trước đây có một số ví dụ không chính xác và sai lệch. Bình luận dưới đây được viết trước tháng 4 năm 2014 đề cập đến một phiên bản cũ hơn.


6
Ví dụ: vì câu trả lời ở trên nói rằng Idempotent operations are often used in the design of network protocolsđây là một ví dụ có liên quan ** GET không giả sử thay đổi bất cứ điều gì trên máy chủ, vì vậy GET là, idempotent. Trong bối cảnh HTTP / servlet, điều đó có nghĩa là cùng một yêu cầu có thể được thực hiện hai lần mà không có hậu quả tiêu cực. ** POST không phải là idempotent.
KNU

1
Là "không quốc tịch" đồng nghĩa với "idempotent"?
Michael Osofsky

2
@MichaelOsofsky: Không, trong setví dụ Python trong câu trả lời, đối tượng tập hợp rõ ràng có trạng thái và cũng cung cấp một số hoạt động tạm thời như discard.
Greg Hewgill

1
@MichaelOsofsky, discardcũng có thể được thực hiện theo cách không trạng thái bằng cách bao gồm trạng thái trong giá trị trả về : discard([my_set, x]) = [my_new_set, x]. Vì vậy, bạn có thể làm discard(discard([my_set, x])). Lưu ý rằng [my_new_set, x]chỉ là một đối số và kiểu của nó là 2-tuple.
Pacerier 10/03/2015

2
@Green Khi sử dụng thuật ngữ tương tự trong bối cảnh bất lực, điều đó có nghĩa là kết quả là như nhau, không phải là hành động . Gọi discard(x)lần thứ hai sẽ có tác dụng tương tự như gọi lần thứ nhất: Tập hợp sẽ không còn chứa x. Tính toán idempotence là về sự mạnh mẽ của một hệ thống. Vì mọi thứ có thể thất bại (ví dụ như mất mạng), khi phát hiện lỗi, bạn sẽ phục hồi như thế nào? Phục hồi đơn giản nhất là chỉ cần làm lại, nhưng điều đó chỉ hoạt động nếu thực hiện lại là không cần thiết. Ví dụ discard(x)là idempotent, nhưng pop()không. Đó là tất cả về phục hồi lỗi.
Andreas

138

Một hoạt động bình thường có thể được lặp đi lặp lại một số lần tùy ý và kết quả sẽ giống như khi nó được thực hiện chỉ một lần. Trong số học, việc thêm số 0 vào một số là không có giá trị.

Idempotence được nói đến rất nhiều trong bối cảnh dịch vụ web "RESTful". REST tìm cách tận dụng tối đa HTTP để cung cấp cho các chương trình quyền truy cập vào nội dung web và thường được đặt trái ngược với các dịch vụ web dựa trên SOAP, chỉ cung cấp các dịch vụ kiểu gọi thủ tục từ xa trong các yêu cầu và phản hồi HTTP.

REST tổ chức một ứng dụng web thành "tài nguyên" (như người dùng Twitter hoặc hình ảnh Flickr) và sau đó sử dụng các động từ HTTP của POST, PUT, GET và DELETE để tạo, cập nhật, đọc và xóa các tài nguyên đó.

Idempotence đóng một vai trò quan trọng trong REST. Nếu bạn NHẬN đại diện cho tài nguyên REST (ví dụ: NHẬN hình ảnh jpeg từ Flickr) và thao tác không thành công, bạn có thể lặp lại GET một lần nữa cho đến khi thao tác thành công. Đối với dịch vụ web, không có vấn đề bao nhiêu lần hình ảnh được nhận. Tương tự, nếu bạn sử dụng dịch vụ web RESTful để cập nhật thông tin tài khoản Twitter của mình, bạn có thể PUT thông tin mới nhiều lần để nhận được xác nhận từ dịch vụ web. PUT-ing nó một ngàn lần cũng giống như PUT-ing nó một lần. Tương tự XÓA-ing một tài nguyên REST một nghìn lần cũng giống như xóa nó một lần. Do đó, idempotence giúp xây dựng một dịch vụ web dễ dàng hơn với các lỗi giao tiếp.

Đọc thêm: Dịch vụ web RESTful , của Richardson và Ruby (tính không thay đổi được thảo luận ở trang 103-104) và luận án tiến sĩ của Roy Fielding về REST . Fielding là một trong những tác giả của HTTP 1.1, RFC-2616, nói về sự không ổn định trong phần 9.1.2 .


Rõ ràng và đơn giản. Tuy nhiên, đây chỉ là một cách giải thích của idempotent.
Pacerier 10/03/2015

10
"idempotence" là một từ quá tải nặng nề vì nó nghe có vẻ hoành tráng và có đủ các ký tự để vượt qua kiểm tra Sesquipedalian. Nếu Benjamin Peirce đã chọn một từ nghe có vẻ đơn giản hơn, chúng ta thậm chí sẽ không có câu hỏi này ngày hôm nay.
Pacerier 11/03/2015

2
Làm thế nào để hiểu nó: Tương tự XÓA-ing một tài nguyên REST một nghìn lần giống như xóa nó một lần ? Bạn không thể xóa tài nguyên một lần nữa nếu nó đã bị xóa.
Xanh

1
@Green nhưng bạn không xóa nó lần đầu tiên. Bạn gửi yêu cầu xóa . Điểm quan trọng là bạn có thể gửi bao nhiêu yêu cầu tùy thích.
Caleth

1
@JimFerrans tôi thấy. Tôi nghĩ rằng có thể có một số lý do liên quan đến chức năng (được tích hợp vào chính HTTP) về lý do tại sao PUT có thể được gửi lại mà không phải lo lắng trong khi POST không thể. Bây giờ, có vẻ như chúng ta chỉ cần tuân thủ các tiêu chuẩn HTTP và hành vi hoàn toàn dựa trên cách máy chủ được triển khai
mangusta

109

Cho dù bạn gọi thao tác bao nhiêu lần, kết quả sẽ giống nhau.


8
Tôi đã nghe thấy idempotent được định nghĩa là một trong hai hoặc dưới đây: 1) Đối với một bộ đầu vào nhất định, nó sẽ luôn trả về cùng một đầu ra. 2) Không tạo ra bất kỳ tác dụng phụ. Câu hỏi của tôi là, nếu một hàm phù hợp với # 1, nhưng không phải là # 2, vì nó dẫn đến một hiệu ứng phụ không liên quan đến tính toán (chẳng hạn như ghi nhật ký yêu cầu vào kho lưu trữ dữ liệu), liệu nó có còn được coi là không hoạt động không?
Keith Bennett

12
Kết quả của việc gọi một hoạt động phải bao gồm trạng thái của hệ thống, vì vậy nếu hoạt động đó có một số tác dụng phụ tích lũy thì nó không phải là tạm thời; tuy nhiên, nếu tác dụng phụ làm cho hệ thống ở trạng thái tương tự cho dù hoạt động được gọi bao nhiêu lần, thì nó có thể không hoạt động.
Robert

4
Ngắn gọn và ngọt ngào, tôi thích kiểu trả lời đó. Không chắc chắn tại sao tôi phải tìm kiếm thuật ngữ này liên tục, đó là một điều không thể ở lại với tôi.
Prancer 2/2/2015

1
@KeithBennett, Định nghĩa thứ hai là sai. "Không có tác dụng phụ" không có nghĩa là bình thường. Chức năng idempotent có thể có tác dụng phụ. Ví dụ: MySQL truncatedelete.
Pacerier 10/03/2015

Kết quả sẽ giống nhau (nghĩa là trạng thái hệ thống), nhưng phản hồi có thể khác nhau (nghĩa là mã trạng thái HTTP trên dịch vụ REST).
G. Steigert

50

Idempotence có nghĩa là áp dụng một hoạt động một lần hoặc áp dụng nó nhiều lần có hiệu quả tương tự.

Ví dụ:

  • Nhân với số không. Cho dù bạn có làm bao nhiêu lần đi chăng nữa thì kết quả vẫn là con số không.
  • Đặt cờ boolean. Cho dù bạn làm điều đó bao nhiêu lần, cờ vẫn được đặt.
  • Xóa một hàng khỏi cơ sở dữ liệu với một ID nhất định. Nếu bạn thử lại, hàng vẫn không còn.

Đối với các hàm thuần túy (các hàm không có tác dụng phụ) thì idempotency ngụ ý rằng f (x) = f (f (x)) = f (f (f (x))) = f (f (f (f (x))) ) = ...... cho tất cả các giá trị của x

Đối với các chức năng có tác dụng phụ , tính không ổn định hơn nữa ngụ ý rằng không có tác dụng phụ bổ sung nào sẽ được gây ra sau ứng dụng đầu tiên. Bạn có thể coi trạng thái của thế giới là một tham số "ẩn" bổ sung cho hàm nếu bạn muốn.

Lưu ý rằng trong một thế giới nơi bạn có các hành động xảy ra đồng thời, bạn có thể thấy rằng các hoạt động mà bạn nghĩ là không còn tồn tại nữa (ví dụ, một luồng khác có thể bỏ đặt giá trị của cờ boolean trong ví dụ trên). Về cơ bản bất cứ khi nào bạn có trạng thái đồng thời và có thể thay đổi, bạn cần suy nghĩ kỹ hơn về tính không ổn định.

Idempotency thường là một tài sản hữu ích trong việc xây dựng các hệ thống mạnh mẽ. Ví dụ: nếu có rủi ro bạn có thể nhận được một tin nhắn trùng lặp từ bên thứ ba, thì việc xử lý tin nhắn hoạt động như một hoạt động bình thường là rất hữu ích để hiệu ứng tin nhắn chỉ xảy ra một lần.


1
Nếu đối với các hàm thuần túy f(x) = f(f(x)), bạn có nghĩa đó f(x){return x+1;}không phải là một hàm thuần túy? bởi vì f(x) != f(f(x)): f(1)cho 2 trong khi f(2)cho 3.
Pacerier 10/03/2015

1
@Pacerier Không, @mikera đang nói ngụ ý thuần túy bình dị f(x) = f(f(x)). Nhưng như @GregHewgill đã đề cập, để định nghĩa này có ý nghĩa, bạn phải xem xét xnhư một đối tượng và fnhư một hoạt động làm thay đổi trạng thái của đối tượng (nghĩa là: đầu ra của flà một đột biến x).
Justin J Stark


16

Chỉ muốn ném ra một trường hợp sử dụng thực sự thể hiện sự bình tĩnh. Trong JavaScript, giả sử bạn đang định nghĩa một loạt các lớp mô hình (như trong mô hình MVC). Cách thức này thường được thực hiện tương đương về mặt chức năng với một cái gì đó như thế này (ví dụ cơ bản):

function model(name) {
  function Model() {
    this.name = name;
  }

  return Model;
}

Sau đó, bạn có thể định nghĩa các lớp mới như thế này:

var User = model('user');
var Article = model('article');

Nhưng nếu bạn cố gắng đưa Userlớp qua model('user'), từ một nơi khác trong mã, nó sẽ thất bại:

var User = model('user');
// ... then somewhere else in the code (in a different scope)
var User = model('user');

Hai nhà Userxây dựng sẽ khác nhau. Đó là,

model('user') !== model('user');

Để làm cho nó không hoạt động , bạn chỉ cần thêm một số loại cơ chế bộ đệm, như thế này:

var collection = {};

function model(name) {
  if (collection[name])
    return collection[name];

  function Model() {
    this.name = name;
  }

  collection[name] = Model;
  return Model;
}

Bằng cách thêm bộ nhớ đệm, mỗi lần bạn thực hiện model('user')nó sẽ là cùng một đối tượng và do đó, nó là idempotent. Vì thế:

model('user') === model('user');

10

Một hoạt động bình thường là một hoạt động, hành động hoặc yêu cầu có thể được áp dụng nhiều lần mà không thay đổi kết quả, tức là trạng thái của hệ thống, ngoài ứng dụng ban đầu.

VÍ DỤ (TIẾP THEO WEB):

IDEMPOTENT: Thực hiện nhiều yêu cầu giống hệt nhau có tác dụng tương tự như thực hiện một yêu cầu. Một tin nhắn trong một hệ thống nhắn tin email được mở và được đánh dấu là "đã mở" trong cơ sở dữ liệu. Người ta có thể mở tin nhắn nhiều lần nhưng hành động lặp đi lặp lại này sẽ chỉ dẫn đến việc tin nhắn đó ở trạng thái "mở". Đây là một hoạt động bình thường. Lần đầu tiên PUT cập nhật tài nguyên bằng thông tin không khớp với tài nguyên (trạng thái của hệ thống), trạng thái của hệ thống sẽ thay đổi khi tài nguyên được cập nhật. Nếu một PUT liên tục cập nhật cùng một tài nguyên thì thông tin trong bản cập nhật sẽ khớp với thông tin đã có trong hệ thống trên mỗi PUT và sẽ không có thay đổi nào về trạng thái của hệ thống. PUT lặp đi lặp lại với cùng thông tin là idempotent:

NON-IDEMPOTENT: Nếu một thao tác luôn gây ra thay đổi trạng thái, như gửi tin nhắn giống nhau cho người dùng nhiều lần, dẫn đến một tin nhắn mới được gửi và lưu trữ trong cơ sở dữ liệu mỗi lần, chúng tôi nói rằng hoạt động đó là KHÔNG TỪNG IDEMPOTENT.

NULLIPOTENT: Nếu một thao tác không có tác dụng phụ, như hoàn toàn hiển thị thông tin trên trang web mà không có bất kỳ thay đổi nào trong cơ sở dữ liệu (nói cách khác bạn chỉ đọc cơ sở dữ liệu), chúng tôi nói rằng hoạt động đó là NULLIPOTENT. Tất cả các GET phải là nullipotent.

Khi nói về trạng thái của hệ thống, rõ ràng chúng ta đang bỏ qua những tác động hy vọng vô hại và không thể tránh khỏi như đăng nhập và chẩn đoán.


9

Hoạt động tạm thời: Các hoạt động không có tác dụng phụ nếu được thực hiện nhiều lần.
Ví dụ : Một hoạt động truy xuất các giá trị từ tài nguyên dữ liệu và nói rằng, in nó

Hoạt động không phải là Idempotent: Các hoạt động sẽ gây ra một số tác hại nếu được thực hiện nhiều lần. (Khi họ thay đổi một số giá trị hoặc trạng thái)
Ví dụ: Một hoạt động rút tiền từ tài khoản ngân hàng


3
Thật ra một câu trả lời sai! đối với hoạt động Idempotent nói rằng "không có tác dụng phụ" là không đúng. đối với các hoạt động không bình thường nói rằng "gây ra một số tác hại" là một câu trả lời khó hiểu.
Saeed Mohtasham

9

Khá là một câu trả lời chi tiết và kỹ thuật. Chỉ cần thêm một định nghĩa đơn giản.

Idempotent = Chạy lại

Ví dụ, Createhoạt động tự nó không được đảm bảo để chạy mà không có lỗi nếu được thực hiện nhiều lần. Nhưng nếu có một hoạt động CreateOrUpdatethì nó nêu khả năng chạy lại (Idempotency).


3
Đây là một định nghĩa lừa đảo. khả năng chạy lại không đảm bảo là bình thường. Một hoạt động có thể được chạy lại và trong mỗi lần chạy, nó có thể thêm các hiệu ứng bổ sung vào kết quả để nó không bị lỗi.
Saeed Mohtasham

7

Một hoạt động tạm thời trên một tập hợp làm cho các thành viên của nó không thay đổi khi được áp dụng một hoặc nhiều lần.

Nó có thể là một phép toán đơn nguyên như tuyệt đối (x) trong đó x thuộc về một tập hợp các số nguyên dương. Ở đây tuyệt đối (tuyệt đối (x)) = x.

Nó có thể là một hoạt động nhị phân như liên kết của một tập hợp với chính nó sẽ luôn trả về cùng một tập hợp.

chúc mừng


Một hoạt động idempotent là một trong đó f (f (x)) = f (x). "Để các thành viên của nó không thay đổi" không phải là một câu trả lời đúng.
Saeed Mohtasham

7

Đó là bất kỳ hoạt động nào mà mọi kết quả thứ n sẽ dẫn đến kết quả đầu ra khớp với giá trị của kết quả thứ 1. Chẳng hạn, giá trị tuyệt đối của -1 là 1. Giá trị tuyệt đối của giá trị tuyệt đối của -1 là 1. Giá trị tuyệt đối của giá trị tuyệt đối của giá trị tuyệt đối của -1 là 1. Và cứ thế.

Xem thêm: Khi nào sẽ là một thời gian thực sự ngớ ngẩn để sử dụng đệ quy?


1
đó là câu trả lời sâu sắc ngay cả sau 10 năm. +1
snr

3

Một ví dụ điển hình về việc hiểu một hoạt động bình thường có thể là khóa xe bằng chìa khóa từ xa.

log(Car.state) // unlocked

Remote.lock();
log(Car.state) // locked

Remote.lock();
Remote.lock();
Remote.lock();
log(Car.state) // locked

locklà một hoạt động bình thường. Ngay cả khi có một số tác dụng phụ mỗi khi bạn chạy lock, như chớp mắt, chiếc xe vẫn trong tình trạng bị khóa, bất kể bạn chạy bao nhiêu lần hoạt động khóa.


1

my 5c: Trong tích hợp và kết nối mạng, tính không thay đổi là rất quan trọng. Một số ví dụ từ đời thực: Hãy tưởng tượng, chúng tôi cung cấp dữ liệu cho hệ thống đích. Dữ liệu được phân phối bởi một chuỗi các tin nhắn. 1. Điều gì sẽ xảy ra nếu chuỗi được trộn trong kênh? (Như các gói mạng luôn làm :)). Nếu hệ thống đích là idempotent, kết quả sẽ không khác. Nếu hệ thống đích phụ thuộc vào thứ tự đúng trong chuỗi, chúng ta phải triển khai resequencer trên trang đích, sẽ khôi phục đúng thứ tự. 2. Điều gì sẽ xảy ra nếu có các thông điệp trùng lặp? Nếu kênh của hệ thống đích không xác nhận kịp thời, hệ thống nguồn (hoặc chính kênh) thường gửi một bản sao khác của tin nhắn. Kết quả là chúng ta có thể có thông điệp trùng lặp ở phía hệ thống đích. Nếu hệ thống đích là idempotent, nó chăm sóc nó và kết quả sẽ không khác nhau. Nếu hệ thống đích không phải là idempotent, chúng ta phải triển khai bộ sao chép ở phía hệ thống đích của kênh.


Tính tạm thời của các yêu cầu đơn lẻ được gửi tách biệt với bất kỳ yêu cầu nào khác (hoặc bất kỳ điều gì khác xảy ra làm thay đổi trạng thái của hệ thống), không giống như các yêu cầu sắp xếp lại. Cả hai yêu cầu PUT HTTP và một yêu cầu XÓA HTTP đều phải là idempotent riêng lẻ - nhưng điều đó không có nghĩa là thứ tự gọi PUT và DELETE trên cùng một URL không quan trọng, vì yêu cầu PUT có thể có tác dụng phụ!
Robin Green

1

Nói ngắn gọn , hoạt động Idempotent có nghĩa là hoạt động sẽ không dẫn đến kết quả khác nhau cho dù bạn có vận hành các hoạt động tạm thời bao nhiêu lần.

Ví dụ, theo định nghĩa về thông số kỹ thuật của HTTP, GET, HEAD, PUT, and DELETElà các hoạt động tạm thời; tuy nhiên POST and PATCHthì không. Đó là lý do tại sao đôi khi POSTđược thay thế bởi PUT.


-4

thử lại an toàn.

Thường là cách dễ nhất để hiểu ý nghĩa của nó trong khoa học máy tính.


1
Thử lại ngụ ý một cái gì đó thất bại lần đầu tiên hoặc trước đó. Không giống lắm.
Lasse V. Karlsen

Ai đã chỉnh sửa câu hỏi của tôi và khiến tôi bỏ phiếu? Đó không phải là văn bản tôi đã đăng ??
teknopaul

Bạn có thể kiểm tra nhật ký chỉnh sửa bằng cách nhấp vào liên kết bên dưới câu trả lời của bạn có nội dung "đã chỉnh sửa X giờ trước" hoặc tương tự.
Lasse V. Karlsen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.