Các mẫu thiết kế của Fix Fix mọi thứ là gì?


74

Trong bài viết năm 2003 này của Stephen Figgins trên linuxdevcenter.com , BitTorrent của Bram Cohen được mô tả là sử dụng mẫu thiết kế "Khắc phục mọi thứ".

Một cách tiếp cận ít phổ biến hơn mà cả hai làm cho BitTorrent khó nắm bắt hơn, nhưng đáng để nghiên cứu, là việc sử dụng tính không thay đổi của Cohen. Một quá trình là không cần thiết khi áp dụng nó nhiều lần không gây ra thay đổi nào nữa. Cohen nói rằng anh ta sử dụng một mẫu thiết kế mà anh ta gọi là "Khắc phục mọi thứ", một chức năng có thể phản ứng với một số thay đổi mà không thực sự chú ý đến tất cả những gì nó có thể thay đổi. Ông giải thích, "bạn lưu ý sự kiện đã xảy ra, sau đó gọi hàm sửa mọi thứ được viết theo cách rất bình thường này, và chỉ cần dọn dẹp bất cứ điều gì có thể xảy ra và tính toán lại tất cả từ đầu." Mặc dù tính không ổn định làm cho một số tính toán khó dễ dàng hơn, nhưng nó làm cho mọi thứ hơi phức tạp. Không phải lúc nào cũng rõ ràng một cuộc gọi sẽ thay đổi, nếu có bất cứ điều gì. Bạn không cần phải biết trước. Bạn được tự do gọi chức năng,

Điều này nghe khá tốt trên khuôn mặt của nó.

Tuy nhiên, đối với tôi, việc gọi một chức năng "sửa chữa mọi thứ" bình thường sẽ cải thiện sự mạnh mẽ của hệ thống với chi phí hiệu quả và có khả năng làm hỏng hệ thống chứa (có thể thích các quy trình lập kế hoạch và thực hiện cẩn thận.).

Tôi không thể nói rằng tôi đã sử dụng nó trước đây, mặc dù. Tôi cũng không thể tìm thấy nguồn cho ứng dụng của mình trực tuyến (nhưng tôi đã tìm thấy nguồn này tuyên bố là dựa trên nó.). Tôi cũng không thể tìm thấy tài liệu tham khảo bên ngoài bài viết này (và tôi cho rằng google-fu của tôi khá tốt) nhưng tôi đã tìm thấy một mục cho "Khả năng của Idempotent" trên SOApotypes.org .

Là ý tưởng này được biết đến nhiều hơn bằng tên khác?

Mẫu thiết kế "Fix Mọi thứ" là gì? Ưu và nhược điểm của nó là gì?


4
Tôi nghi ngờ tên cũng là một tham chiếu đến ý tưởng về điểm cố định của hàm, x = f (x). Cho dù bạn áp dụng f cho x bao nhiêu lần , kết quả vẫn như nhau. Khi bạn đạt được kết quả chính xác, xử lý lại kết quả chính xác sẽ trả về kết quả đúng như vậy.
9000

7
Lưu ý rằng bất kỳ ai cũng có thể đặt bất kỳ tên nào cho bất kỳ thứ gì họ muốn, nhưng điều đó không làm cho nó trở thành một mẫu phần mềm nổi tiếng. Idempotency là một khái niệm nổi tiếng theo đúng nghĩa của nó; có vẻ như nó được sử dụng một cách sáng tạo ở đây.
Robert Harvey

1
Điều này nhắc nhở tôi về cách Vòng lặp sự kiện chính được triển khai trên Mac OS. Đó là một chức năng duy nhất đáp ứng với bất kỳ Sự kiện nào và thường được cấu trúc để kiểm tra trạng thái của tất cả các điều khiển và cập nhật toàn bộ giao diện người dùng khi cần. Vô tư, thực sự.
Lucas

3
This sounds quite nice on the face of it. Có thật không? Nghe có vẻ kinh khủng với tôi!
Michael

3
@Michael Bạn không thích quản lý gói? Chúng hoạt động theo cùng một khái niệm, chỉ ở quy mô nhỏ hơn: Đánh dấu những gì bạn muốn hệ thống trông như thế nào, chạy "sửa mọi thứ", nó cài đặt / gỡ bỏ / nâng cấp khi thích hợp, nhưng chỉ có bất cứ điều gì để làm nếu có thay đổi.
Izkata

Câu trả lời:


100

Giả sử bạn có một trang HTML khá phức tạp - nếu bạn chọn thứ gì đó trong một lần thả xuống, một điều khiển khác có thể xuất hiện hoặc các giá trị trong điều khiển thứ ba có thể thay đổi. Có hai cách bạn có thể tiếp cận điều này:

  1. Viết một trình xử lý riêng, cho mỗi và mọi điều khiển, đáp ứng các sự kiện trên điều khiển đó và cập nhật các điều khiển khác khi cần.

  2. Viết một trình xử lý duy nhất xem trạng thái của tất cả các điều khiển trên trang và chỉ sửa mọi thứ .

Cuộc gọi thứ hai là "idempotent" bởi vì bạn có thể gọi đi gọi lại nhiều lần và các điều khiển sẽ luôn được sắp xếp hợp lý. Trong khi đó (các) cuộc gọi đầu tiên có thể có vấn đề nếu cuộc gọi bị mất hoặc lặp lại, ví dụ: nếu một trong những người xử lý thực hiện chuyển đổi.

Logic cho cuộc gọi thứ hai sẽ tối nghĩa hơn một chút, nhưng bạn chỉ phải viết một trình xử lý.

Và bạn luôn có thể sử dụng cả hai giải pháp, gọi chức năng "sửa chữa mọi thứ" là cần thiết "chỉ để ở bên an toàn".

Cách tiếp cận thứ hai đặc biệt tốt khi trạng thái có thể đến từ các nguồn khác nhau, ví dụ từ đầu vào của người dùng so với kết xuất từ ​​máy chủ. Trong ASP.NET, kỹ thuật này chơi rất tốt với khái niệm postback vì bạn chỉ cần chạy chức năng sửa mọi thứ bất cứ khi nào bạn kết xuất trang.

Bây giờ tôi đã đề cập đến các sự kiện bị mất hoặc lặp đi lặp lại và nhận được trạng thái từ các nguồn khác nhau, tôi nghĩ rõ ràng cách tiếp cận này ánh xạ tốt đến một không gian có vấn đề như của BitTorrent.

Nhược điểm? Rõ ràng con lừa là có một hiệu suất thành công bởi vì nó ít hiệu quả hơn để vượt qua mọi thứ mọi lúc. Nhưng một giải pháp như BitTorrent được tối ưu hóa để mở rộng quy mô chứ không phải mở rộng quy mô, vì vậy nó tốt cho loại điều đó. Tùy thuộc vào vấn đề bạn đang cố gắng giải quyết, nó có thể không phù hợp với bạn.


9
Đối với tôi, dường như MVC là điển hình của "Khắc phục mọi thứ": khi bạn sửa đổi mô hình sau đó vẽ lại khung nhìn từ đầu, khung nhìn chỉ được vẽ lại hoàn toàn, mà không cố gắng thần thánh những phần mà hành động có thể bị ảnh hưởng.
Matthieu M.

3
Điều này về cơ bản giống như nguyên tắc đằng sau các hệ thống như Saltstack, Ansible và Nix. Đưa ra một mô tả về cấu hình, về mặt lý thuyết bạn có thể đưa một số hệ thống khác nhau vào cùng một trạng thái kết thúc.
kojiro

1
@MatthieuM. React , khá phổ biến trong phát triển frontend, cũng giống như vậy ngoại trừ nó có hiệu ứng ảo khác biệt nên nó chỉ cập nhật dom thực sự với những thay đổi thực tế
Izkata

2
@Izkata Thậm chí hơn cả React, câu trả lời này khiến tôi nghĩ về Redux.
Kevin

2
Có thể hữu ích khi chỉ ra rằng "sửa chữa mọi thứ" và idempotent là những thứ khác nhau: "sửa chữa mọi thứ" thường là tạm thời (nhưng không cần phải như vậy) và các hoạt động bình thường không cần sửa chữa mọi thứ hoặc thậm chí không có hiệu suất hình phạt - chỉ đưa ra kết quả tương tự khi thực hiện hai lần.
Hans-Peter Störr

15

Tôi nghĩ rằng bài báo này hơi cũ vì khi tôi đọc nó, đây thực sự không phải là một ý tưởng không chính thống hay mới. Ý tưởng này được trình bày dưới dạng một mẫu riêng biệt khi nó thực sự chỉ là một triển khai Observer đơn giản. Nghĩ lại những gì tôi đang làm lúc đó, tôi nhớ làm việc dựa trên logic để ngồi sau một giao diện hơi phức tạp với một số bảng khác nhau với dữ liệu phụ thuộc lẫn nhau. Người dùng có thể thay đổi giá trị và / hoặc chạy một thói quen tối ưu hóa và dựa trên những hành động đó, các sự kiện được tạo ra mà UI sẽ lắng nghe và cập nhật khi cần. Có một số vấn đề trong quá trình phát triển trong đó một số bảng nhất định sẽ không cập nhật khi cần. Cách khắc phục (nằm trong thiết kế) là tạo các sự kiện từ các sự kiện khác. Cuối cùng, đến lúc mọi thứ đã hoạt động tốt, hầu như mọi thay đổi dẫn đến tất cả các bảng để làm mới. Tất cả sự phức tạp của việc cố gắng cô lập khi một bảng điều khiển nhất định cần làm mới là vô ích. Và dù sao nó cũng không thành vấn đề. Đó là một tối ưu hóa sớm. Tôi sẽ tiết kiệm được rất nhiều thời gian và công sức bằng cách đơn giản thu gọn tất cả vào một sự kiện duy nhất làm mới mọi thứ.

Có vô số hệ thống được thiết kế theo kiểu "sửa chữa mọi thứ" hoặc làm mới mọi thứ. Hãy nghĩ về tất cả các giao diện CRUD thêm / cập nhật một hàng và sau đó yêu cầu DB. Đây không phải là một cách tiếp cận kỳ lạ, nó chỉ là giải pháp không thông minh rõ ràng. Bạn phải nhận ra rằng vào năm 2003, đó là chiều cao của 'cơn sốt mẫu'. Từ những gì tôi có thể nói, mọi người nghĩ rằng việc đặt tên cho các mẫu mới sẽ là con đường dẫn đến sự nổi tiếng và giàu có. Đừng hiểu sai ý tôi, tôi nghĩ khái niệm mẫu là một thứ cực kỳ hữu ích để mô tả các giải pháp trong bản tóm tắt. Mọi thứ chỉ đi ra khỏi đường ray một chút. Thật không may vì nó tạo ra rất nhiều sự hoài nghi về khái niệm mẫu nói chung. Chỉ trong bối cảnh này, thật hợp lý khi nói về điều này như một giải pháp 'không chính thống'. Nó ' s tương tự như chính thống xung quanh các thùng chứa ORM hoặc DI. Không sử dụng chúng được coi là không chính thống mặc dù mọi người đã xây dựng phần mềm từ lâu trước khi các công cụ này tồn tại và trong nhiều trường hợp những công cụ đó là quá mức cần thiết.

Vì vậy, quay trở lại 'sửa chữa mọi thứ'. Một ví dụ đơn giản là tính toán phương tiện. Giải pháp đơn giản là tính tổng các số và chia cho giá trị chính của các giá trị. Nếu bạn thêm hoặc sửa đổi một số, bạn chỉ cần làm lại từ đầu. Bạn có thể theo dõi tổng và số lượng các số và khi ai đó thêm một số, bạn tăng số lượng và thêm nó vào tổng. Bây giờ bạn không thêm lại tất cả các số. Nếu bạn đã từng làm việc với Excel với công thức tham chiếu một phạm vi và sửa đổi một giá trị trong phạm vi đó, bạn có một ví dụ về mẫu 'sửa mọi thứ', tức là bất kỳ công thức nào có tham chiếu đến phạm vi đó sẽ tính lại bất kể liệu có giá trị đó có liên quan (ví dụ: sử dụng cái gì đó như sumif ()).

Điều này không có nghĩa là đây không phải là một lựa chọn thông minh trong bối cảnh nhất định. Trong ví dụ trung bình, giả sử bây giờ chúng ta cần hỗ trợ cập nhật. Bây giờ tôi cần biết giá trị cũ bằng cách nào đó và chỉ thay đổi tổng theo đồng bằng. Không ai trong số này thực sự là thách thức cho đến khi bạn xem xét cố gắng làm điều này trong một môi trường phân tán hoặc đồng thời. Bây giờ bạn phải xử lý tất cả các loại vấn đề thời gian gai góc và có khả năng bạn sẽ tạo ra một nút cổ chai lớn làm chậm mọi thứ hơn là tính toán lại.

Kết quả cuối cùng ở đây là 'sửa chữa mọi thứ' hoặc 'làm mới mọi thứ' phương pháp dễ dàng hơn nhiều để có được quyền. Bạn có thể làm cho một cách tiếp cận tinh vi hơn hoạt động nhưng nó phức tạp hơn nhiều và do đó có nhiều khả năng bị sai sót. Ngoài ra, trong rất nhiều bối cảnh, phương pháp 'làm mới mọi thứ' có thể hiệu quả hơn. Ví dụ, sao chép trên các phương pháp ghi thường chậm hơn đối với các cách tiếp cận đơn luồng nhưng khi bạn có độ đồng thời cao, nó có thể cho phép bạn tránh các khóa và do đó cung cấp hiệu suất tốt hơn. Trong các trường hợp khác, nó có thể cho phép bạn thay đổi hàng loạt cùng nhau một cách hiệu quả. Vì vậy, đối với hầu hết các vấn đề, có lẽ bạn muốn bắt đầu với một cách tiếp cận mọi thứ trừ khi bạn có một lý do cụ thể tại sao bạn không thể làm điều đó và sau đó lo lắng về việc làm một cái gì đó phức tạp hơn một khi bạn có nhu cầu.


2
Tôi khá chắc chắn rằng Excel dự định chỉ tính toán lại các ô phụ thuộc vào thay đổi, đó là lý do tại sao có cách kích hoạt tất cả các ô để tính toán lại: superuser.com/questions/448376/ . )
Aaron Hall

@AaronHall Nếu có, đó là một triển khai thực sự tồi tệ. Tôi thường xuyên xem nó tiêu thụ 100% của 7 CPU trong 15-30 phút để tính toán, ví dụ 60.000 tế bào. Các tính toán không phức tạp. Tôi thường viết các chương trình Python có thể thực hiện mọi thứ trong trang tính trong vài giây kể cả khởi động Python. Đây là dự đoán tốt nhất của tôi về cách nó có thể mất nhiều thời gian. Nó có thể là một cái gì đó khác tôi cho rằng. Ngoài ra còn có một số lỗi thực sự cũ trong Excel có thể là lý do cho tính năng đó.
JimmyJames

1
@AaronHall cũng có thể với người dùng đó tính toán tự động đã bị vô hiệu hóa trên trang tính. Tôi thường làm điều này trên các sổ làm việc lớn vì tôi không có 15 phút rảnh rỗi mỗi khi tôi nhấn enter.
JimmyJames

@AaronHall Tôi nghĩ nhiều hơn một chút và bạn có một điểm. Giả định của tôi có khả năng quá rộng. Tôi đã cập nhật câu trả lời để tôi tập trung hơn vào điều gì đó mà tôi tin tưởng hơn.
JimmyJames

2
@JimmyJames: Điểm tôi muốn nói là cách tiếp cận tốt nhất có thể thay đổi tùy theo hoàn cảnh và "sửa mọi thứ" có thể được chia thành "háo hức sửa mọi thứ trên từng thay đổi riêng lẻ" và "sửa chữa mọi thứ một cách lười biếng sau khi mọi thay đổi hoàn tất ".
supercat

4

Không chắc chắn đó là "mẫu thiết kế", nhưng tôi sẽ phân loại loại hành vi đó là cấu hình trạng thái kết thúc hoặc cấu hình trạng thái mong muốn , theo mạch của Puppet, Chef hoặc Powershell DSC.

Các giải pháp đó thường hoạt động ở cấp quản lý hệ thống, không phải ở cấp logic nghiệp vụ như câu hỏi mô tả, nhưng đó là mô hình tương tự và mặc dù các công cụ đó thường có tính chất khai báo, các nguyên tắc tương tự có thể được áp dụng trong mã thủ tục hoặc kịch bản.


1

Tôi đã sử dụng chủ yếu trong giao diện người dùng. Điều tuyệt vời là bạn viết nó một lần và nó xử lý mọi thứ từ đơn giản nhất đến trường hợp khó nhất đều tốt (ví dụ: nếu người dùng xoay màn hình, hoặc trên máy tính xách tay / máy tính để bàn nếu người dùng thay đổi kích thước cửa sổ và hầu như mọi thứ thay đổi ).

Không có nhiều lý do để lo lắng về hiệu quả. Trong giao diện người dùng, những thứ đắt tiền là những thứ như vẽ lại một vật phẩm đã được di chuyển. Việc tính toán nơi mỗi mục đi và mức độ lớn của nó thường khá nhanh. Tất cả bạn phải chắc chắn là bất cứ khi nào bạn thấy rằng một mục nên ở chính xác nơi nó thuộc về, không có mã nào được thực thi để di chuyển nó. Những thay đổi thực sự là tất cả những điều mà bạn phải làm bằng mọi cách.


0

Âm thanh như nguyên tắc lập trình phản ứng. "Khắc phục mọi thứ" nhìn vào trạng thái "cốt lõi" hiện tại và tuyên truyền mọi thứ khác sẽ bị ảnh hưởng - "trạng thái tính toán". Nếu bạn tối ưu hóa dẫn xuất này, nó có thể đạt hiệu quả cao, a-la React, nếu được thực hiện một cách ngây thơ, hiệu suất có thể không tối ưu mặc dù nó vẫn có thể đủ nhanh.

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.