Dễ dàng lý luận về vấn đề này - điều đó có nghĩa là gì? [đóng cửa]


49

Tôi đã nghe rất nhiều lần khi các nhà phát triển khác sử dụng cụm từ đó để "quảng cáo" một số mẫu hoặc phát triển các thực tiễn tốt nhất. Hầu hết thời gian cụm từ này được sử dụng khi bạn đang nói về lợi ích của lập trình chức năng.

Cụm từ "Dễ lý luận về" đã được sử dụng, mà không có bất kỳ lời giải thích hoặc mẫu mã nào. Vì vậy, đối với tôi, nó trở thành giống như từ "buzz" tiếp theo, mà các nhà phát triển "có kinh nghiệm" hơn sử dụng trong các cuộc nói chuyện của họ.

Câu hỏi: Bạn có thể cung cấp một số ví dụ về "Không dễ lý luận về", vì vậy nó có thể được so sánh với các ví dụ "Dễ lý luận về" không?


4
@MartinMaat một cụm từ chính xác hơn được sử dụng rộng rãi là lý luận tương đương, tôi muốn đề xuất rằng đây có thể là những gì Fabio theo sau
jk.

3
Tôi thích sử dụng cụm từ "tải nhận thức" cho loại điều này.
Baldrickk

16
Bạn có biết lý do về các chương trình có nghĩa là gì?
Bergi

5
Theo nghĩa không chính thức, tôi sử dụng điều này có nghĩa là một giải pháp đủ đơn giản để hiểu (nói chung) kết quả sẽ là gì cho bất kỳ đầu vào cụ thể nào mà không cần kiểm tra nó. Điều đó có nghĩa là đối với bất kỳ bộ đầu vào nào, kết quả sẽ không có gì đáng ngạc nhiên. Các giải pháp có trường hợp góc không rõ ràng, ví dụ, rất khó để lý do. Chủ yếu tôi sử dụng điều này trong tham chiếu đến sự mạnh mẽ.
JimmyJames

7
Tôi rất có lỗi khi thường xuyên sử dụng "lý do dễ hiểu hơn"; Tuy nhiên, tôi lưu ý rằng tôi cố gắng cẩn thận để nói so sánh dễ hơn là dễ tuyệt đối . Có một ngày trong cuộc đời tôi khi tôi có thể suy luận về việc không có phần mềm nào cả, vì vậy ngày đó không dễ dàng gì; nó trở nên dễ dàng chỉ bằng cách dành rất nhiều thời gian và nỗ lực. Để nói rằng bất kỳ vấn đề lập trình nào là dễ dàng là có lập trường nổi bật đối với bất kỳ ai có thể không (chưa) thấy nó dễ dàng. Để nói rằng một mô hình dễ hơn một mô hình khác là nói rằng có ít khái niệm liên quan hơn, ít bộ phận chuyển động hơn, v.v.
Eric Lippert

Câu trả lời:


58

Theo tôi, cụm từ "dễ lý luận về", đề cập đến mã dễ "thực thi trong đầu bạn".

Khi nhìn vào một đoạn mã, nếu nó ngắn, được viết rõ ràng, với tên hay và sự đột biến tối thiểu của các giá trị, thì làm việc về mặt tinh thần thông qua những gì mã làm là một nhiệm vụ dễ dàng (tương đối).

Một đoạn mã dài với tên kém, các biến liên tục thay đổi giá trị và phân nhánh phức tạp thường sẽ yêu cầu ví dụ như một cây bút và mảnh giấy để theo dõi trạng thái hiện tại. Do đó, mã như vậy không thể dễ dàng làm việc thông qua trong đầu của bạn, vì vậy mã đó không dễ lý do.


29
Với một cảnh báo nhỏ rằng cho dù bạn đặt tên cho các biến của mình tốt đến đâu, một chương trình cố gắng từ chối phỏng đoán của Goldbach vốn đã khó "thực thi", trong đầu bạn hoặc ở nơi khác. Nhưng vẫn có thể dễ dàng lý luận về điều đó, theo nghĩa là dễ dàng thuyết phục bản thân rằng nếu tuyên bố đã tìm thấy một ví dụ ngược lại thì đó là sự thật ;-)
Steve Jessop

4
Tôi sẽ không bao giờ muốn thực thi mã trong đầu của tôi. Điều đó, với tôi, sẽ là chương trình cuối cùng của "không dễ để lý luận." Tôi muốn có thể đưa ra các tuyên bố dự đoán về những gì máy tính sẽ làm mà không cần thực hiện nó. Mã "dễ lý luận về" là mã không phải được thực thi trong đầu của bạn, thay vào đó, nó có thể được lý do.
Cort Ammon

1
Làm thế nào người ta có thể trả lời một câu hỏi về lý luận về mã mà không đề cập đến xác minh chính thức ? Câu trả lời này cho thấy lý do về mã là không chính thức và đặc biệt. Nó không, nó thường được thực hiện với các phương pháp toán học và chăm sóc rất tuyệt vời. Có một số tính chất toán học làm cho mã "dễ suy luận" theo nghĩa khách quan (các hàm thuần túy, để đưa ra một ví dụ rất dễ). Tên của các biến không liên quan gì đến việc "lý luận" về mã dễ dàng như thế nào, ít nhất là không theo bất kỳ ý nghĩa chính thức nào.
Polygnome

3
@Polygnome Lý do về mã thường không được thực hiện với các phương pháp toán học và chăm sóc rất tuyệt vời. Khi tôi viết điều này, mọi người suy luận về mã không chính thức đang vượt xa các nhà tiếp cận toán học hàng triệu đến một, ít nhất, hoặc vì vậy tôi nghĩ.
Kaz

2
@Polygnome "Code easy to reason about" almost exclusively alludes to its mathematical properties and formal verification- nghe có vẻ như là một câu trả lời cho câu hỏi. Bạn có thể muốn đăng nó như một câu trả lời thay vì không đồng ý về những gì câu trả lời (chủ quan) trong các bình luận.
Dukeling

47

Một cơ chế hoặc một đoạn mã rất dễ để lý giải khi bạn cần tính đến một vài điều để dự đoán những gì nó sẽ làm và những điều bạn cần phải tính đến là dễ dàng có sẵn.

Các hàm thực sự không có tác dụng phụ và không có trạng thái dễ dàng lý do bởi vì đầu ra hoàn toàn được xác định bởi đầu vào, nằm ngay trong các tham số.

Ngược lại, một đối tượng có trạng thái khó lý luận hơn nhiều, bởi vì bạn phải tính đến trạng thái của đối tượng khi phương thức được gọi, điều đó có nghĩa là bạn phải suy nghĩ về những tình huống khác có thể dẫn đến đối tượng đang ở trong một tiểu bang cụ thể.

Thậm chí tệ hơn là các biến toàn cục: để lý giải về mã đọc biến toàn cục, bạn cần hiểu mã đó có thể được đặt ở đâu và tại sao - và thậm chí có thể không dễ dàng tìm thấy tất cả các vị trí đó.

Điều khó nhất để giải thích là lập trình đa luồng với trạng thái chia sẻ, bởi vì không chỉ bạn có trạng thái, bạn có nhiều luồng thay đổi cùng một lúc, vì vậy hãy suy luận về việc một đoạn mã sẽ làm gì khi được thực thi bởi một luồng bạn phải cho phép khả năng tại mỗi điểm thực thi, một số luồng khác (hoặc một vài trong số chúng!) có thể thực thi bất kỳ phần nào khác của mã và thay đổi dữ liệu bạn đang hoạt động ngay dưới mắt bạn. Về lý thuyết, điều đó có thể được quản lý bằng mutexes / màn hình / phần quan trọng / bất cứ điều gì bạn gọi nó, nhưng trong thực tế, không có con người nào thực sự có thể làm điều đó một cách đáng tin cậy trừ khi họ quyết định giới hạn trạng thái chia sẻ và / hoặc song song rất nhỏ các phần của mã.


9
Tôi đồng ý với câu trả lời này, nhưng ngay cả với các hàm thuần túy, các cách tiếp cận khai báo (như CSS, hoặc XSLT, makehoặc thậm chí là chuyên môn hóa và nạp chồng mẫu C ++) có thể đưa bạn trở lại vị trí xem xét toàn bộ chương trình. Ngay cả khi bạn nghĩ rằng bạn đã tìm thấy định nghĩa của một cái gì đó, ngôn ngữ cho phép khai báo cụ thể hơn ở bất cứ đâu trong chương trình để ghi đè lên nó. IDE của bạn có thể giúp với điều này.
Steve Jessop

4
Tôi muốn nói thêm rằng trong kịch bản đa luồng, bạn cũng phải có một sự hiểu biết sâu sắc một cách hợp lý về những gì các trình giải mã cấp dưới của bạn hướng tới: một hoạt động có vẻ nguyên tử trong nguồn có thể có các điểm gián đoạn bất ngờ trong quá trình thực thi.
Jared Smith

6
@SteveJessop: Thật vậy, điểm này thường bị bỏ qua. Có một lý do tại sao C # làm cho bạn nói khi bạn muốn một phương thức được ghi đè thay vì lặng lẽ làm cho tính quá mức mặc định; chúng tôi muốn vẫy cờ nói rằng "tính chính xác của chương trình của bạn có thể phụ thuộc vào mã bạn không thể tìm thấy tại thời điểm biên dịch" tại thời điểm này. (Điều đó nói rằng, tôi cũng ước rằng "niêm phong" là mặc định cho các lớp trong C #.)
Eric Lippert

@EricLippert Lý do cuối cùng để sealedkhông được mặc định là gì?
Zev Spitz

@ZevSpitz: Quyết định đó đã được đưa ra từ lâu trước thời của tôi; Tôi không biết.
Eric Lippert

9

Trong trường hợp lập trình chức năng, ý nghĩa của Easy Easy để lý luận về chủ yếu là chủ yếu mang tính quyết định. Do đó, tôi có nghĩa là một đầu vào nhất định sẽ luôn dẫn đến cùng một đầu ra. Bạn có thể làm bất cứ điều gì bạn muốn với chương trình, miễn là bạn không chạm vào đoạn mã đó, nó sẽ không bị hỏng.

Mặt khác, OO thường khó lý do hơn vì "đầu ra" được tạo ra phụ thuộc vào trạng thái bên trong của mọi đối tượng liên quan. Cách điển hình mà nó biểu hiện là tác dụng phụ không mong muốn : khi thay đổi một phần của mã, một phần dường như không liên quan sẽ bị phá vỡ.

... nhược điểm của lập trình chức năng tất nhiên là trong thực tế, rất nhiều thứ bạn muốn làm là IO và quản lý trạng thái.

Tuy nhiên, có rất nhiều điều khác khó giải thích hơn và tôi đồng ý với @Kilian rằng đồng thời là một ví dụ điển hình. Hệ thống phân tán cũng vậy.


5

Tránh thảo luận rộng hơn và giải quyết câu hỏi cụ thể:

Bạn có thể cung cấp một số ví dụ về "Không dễ lý luận về", vì vậy nó có thể được so sánh với các ví dụ "Dễ lý luận về" không?

Tôi giới thiệu bạn đến "Câu chuyện về Mel, một lập trình viên thực thụ" , một phần của văn hóa dân gian lập trình có từ năm 1983 và do đó được coi là 'huyền thoại', cho nghề nghiệp của chúng tôi.

Nó kể câu chuyện về một lập trình viên viết mã ưa thích các kỹ thuật phức tạp bất cứ khi nào có thể, bao gồm mã tự tham chiếu và tự sửa đổi, và cố tình khai thác các lỗi máy:

trên thực tế, một vòng lặp vô hạn rõ ràng đã được mã hóa theo cách để tận dụng lỗi mang tràn. Thêm 1 vào một lệnh được giải mã là "Tải từ địa chỉ x" thường mang lại "Tải từ địa chỉ x + 1". Nhưng khi x đã là địa chỉ cao nhất có thể, không chỉ địa chỉ bao quanh bằng 0, mà 1 được mang vào các bit mà opcode sẽ được đọc, thay đổi opcode từ "tải từ" sang "nhảy sang" rằng hướng dẫn đầy đủ đã thay đổi từ "tải từ địa chỉ cuối" sang "nhảy đến địa chỉ 0".

Đây là một ví dụ về mã "khó lý do".

Tất nhiên, Mel sẽ không đồng ý ...


1
+1 để tham khảo câu chuyện về Mel, một trong những mục yêu thích lâu năm của tôi.
John Bollinger

3
Đọc Câu chuyện về Mel ở đây, vì bài viết trên Wikipedia không liên kết với nó.
TRiG

@TRiG chú thích 3 trên trang, không?
AakashM

@AakashM Bằng cách nào đó quản lý để bỏ lỡ điều đó.
TRiG

5

Tôi có thể cung cấp một ví dụ, và một ví dụ rất phổ biến.

Hãy xem xét mã C # sau đây.

// items is List<Item>
var names = new List<string>();
for (var i = 0; i < items.Count; i++)
{
    var item = items[i];
    var mangled = MyMangleFunction(item.Name);
    if (mangled.StartsWith("foo"))
    {
        names.Add(mangled);
    }
}

Bây giờ hãy xem xét sự thay thế này.

// items is List<Item>
var names = items
    .Select(item => MyMangleFunction(item.Name))
    .Where(s => s.StartsWith("foo"))
    .ToList();

Trong ví dụ thứ hai, tôi biết chính xác mã này đang làm gì trong nháy mắt. Khi tôi nhìn thấy Select, tôi biết một danh sách các mặt hàng đang được chuyển đổi thành một danh sách các thứ khác. Khi tôi nhìn thấy Where, tôi biết rằng một số mặt hàng nhất định đang được lọc ra. Trong nháy mắt, tôi có thể hiểu những gì namesvà sử dụng hiệu quả của nó.

Khi tôi nhìn thấy một forvòng lặp, tôi không biết điều gì đang xảy ra với nó cho đến khi tôi thực sự đọc qua mã. Và đôi khi tôi phải theo dõi thông qua nó để chắc chắn rằng tôi đã tính đến tất cả các tác dụng phụ. Tôi phải làm một chút công việc để thậm chí hiểu được tên là gì (ngoài định nghĩa loại) và làm thế nào để sử dụng nó một cách hiệu quả. Vì vậy, ví dụ đầu tiên khó lý luận hơn so với ví dụ thứ hai.

Cuối cùng, việc dễ dàng lý luận ở đây cũng phụ thuộc vào việc hiểu các phương pháp LINQ SelectWhere. Nếu bạn không biết họ, thì mã thứ hai khó lý giải hơn ban đầu. Nhưng bạn chỉ phải trả chi phí để hiểu họ một lần. Bạn phải trả chi phí để hiểu một forvòng lặp mỗi khi bạn sử dụng một lần nữa mỗi lần nó thay đổi. Đôi khi chi phí đáng để trả, nhưng thường thì "dễ lý luận hơn" lại quan trọng hơn nhiều.


2

Một cụm từ liên quan là (tôi diễn giải),

Mã này không đủ để " không có lỗi rõ ràng ": thay vào đó, nó phải có " rõ ràng không có lỗi ".

Một ví dụ về "lý do dễ hiểu" tương đối có thể là RAII .

Một ví dụ khác có thể là tránh cái ôm chết người : nếu bạn có thể giữ một khóa và có được một khóa khác, và có rất nhiều khóa, thật khó để chắc chắn rằng không có kịch bản nào trong đó có thể xảy ra cái ôm chết người. Thêm quy tắc như "chỉ có một khóa (toàn cầu)" hoặc "bạn không được phép có khóa thứ hai trong khi bạn giữ khóa thứ nhất", khiến hệ thống tương đối dễ hiểu.


1
Hừm. Tôi không chắc RAII rất dễ lý do. Chắc chắn, thật dễ hiểu về mặt khái niệm , nhưng thực sự khó khăn hơn để lý giải về (nghĩa là dự đoán) hành vi của mã sử dụng RAII rộng rãi. Ý tôi là, về cơ bản nó là hàm gọi vô hình ở cấp phạm vi. Thực tế là nhiều người gặp khó khăn khi suy luận về điều này rất đơn giản nếu bạn đã từng thực hiện bất kỳ chương trình COM nào .
Cody Grey

Ý tôi là tương đối dễ (C ++ so với C): ví dụ: sự tồn tại của hàm tạo hỗ trợ ngôn ngữ có nghĩa là lập trình viên không thể tạo / có / sử dụng một đối tượng mà họ quên khởi tạo, v.v.
ChrisW

Ví dụ dựa trên COM đó có vấn đề vì nó trộn các kiểu, tức là con trỏ thông minh kiểu C ++ ( CComPtr<>) với hàm kiểu C ( CoUninitialize()). Tôi cũng thấy đó là một ví dụ kỳ quái, theo như tôi nhớ bạn đã gọi CoInitialize / CoUninitialize ở phạm vi mô-đun và trong toàn bộ thời gian mô-đun, ví dụ như trong mainhoặc trong DllMainvà không phải trong một phạm vi chức năng cục bộ tồn tại ngắn như trong ví dụ .
ChrisW

Đó là một ví dụ đơn giản hóa quá mức cho mục đích minh họa. Bạn hoàn toàn đúng khi COM được khởi tạo ở phạm vi mô-đun, nhưng hãy tưởng tượng ví dụ của Raymond (như ví dụ của Larry) là hàm nhập điểm ( main) cho một ứng dụng. Bạn khởi tạo COM khi khởi động, và sau đó bạn hủy kích hoạt nó ngay trước khi thoát. Ngoại trừ bạn có các đối tượng toàn cầu, như con trỏ thông minh COM, sử dụng mô hình RAII. Về phong cách pha trộn: một đối tượng toàn cầu khởi tạo COM trong ctor của nó và chưa được khởi tạo trong dtor của nó là hoàn toàn khả thi, và những gì Raymond gợi ý, nhưng nó tinh tế và không dễ lý luận.
Cody Grey

Tôi sẽ lập luận rằng, theo nhiều cách, lập trình COM dễ dàng lý luận hơn trong C, bởi vì mọi thứ đều là một lời gọi hàm rõ ràng. Không có gì ẩn hoặc vô hình đang diễn ra sau lưng bạn. Đó là một công việc nhiều hơn một chút (nghĩa là tẻ nhạt hơn), bởi vì bạn phải viết thủ công tất cả các cuộc gọi chức năng đó và quay lại và kiểm tra công việc của bạn để xem bạn đã thực hiện đúng chưa, nhưng tất cả đều nằm trống, đó là chìa khóa để làm cho nó dễ dàng để lý do về. Nói cách khác, "đôi khi con trỏ thông minh chỉ là quá thông minh" .
Cody Grey

2

Mấu chốt của lập trình là phân tích trường hợp. Alan Perlis đã nhận xét về điều này trong Epigram # 32: Các lập trình viên không được đo lường bằng sự khéo léo và logic của họ mà bằng sự hoàn thiện trong phân tích trường hợp của họ.

Một tình huống là dễ dàng để lý do nếu phân tích trường hợp là dễ dàng. Điều này có nghĩa là có một vài trường hợp cần xem xét, hoặc, không thành công, một vài trường hợp đặc biệt có thể có một số không gian lớn của các trường hợp, nhưng sụp đổ do một số thông thường, hoặc chịu thua một kỹ thuật lý luận như cảm ứng.

Chẳng hạn, một phiên bản đệ quy của thuật toán thường dễ lý luận hơn phiên bản bắt buộc, bởi vì nó không đóng góp các trường hợp thừa phát sinh thông qua đột biến của các biến trạng thái hỗ trợ không xuất hiện trong bản án đệ quy. Hơn nữa, cấu trúc của đệ quy sao cho phù hợp với mô hình chứng minh bằng toán học. Chúng ta không phải xem xét sự phức tạp như các biến thể vòng lặp và các điều kiện tiên quyết nghiêm ngặt yếu nhất và không có điều gì.

Một khía cạnh khác của điều này là cấu trúc của không gian trường hợp. Dễ dàng hơn để lý giải về một tình huống có phân chia phẳng, hoặc chủ yếu là phẳng cho các trường hợp so với tình huống phân cấp: các trường hợp với các trường hợp phụ và các trường hợp phụ, v.v.

Một thuộc tính của các hệ thống đơn giản hóa lý luận là tính trực giao : đây là thuộc tính mà các trường hợp chi phối các hệ thống con vẫn độc lập khi các hệ thống con đó được kết hợp. Không có sự kết hợp nào làm phát sinh "trường hợp đặc biệt". Nếu một trường hợp bốn trường hợp một cái gì đó được kết hợp với một trường hợp ba trường hợp một cái gì đó trực giao, có mười hai trường hợp, nhưng lý tưởngmỗi trường hợp là sự kết hợp của hai trường hợp vẫn độc lập. Theo một nghĩa nào đó, thực sự không có mười hai trường hợp; các kết hợp chỉ là "hiện tượng giống như trường hợp khẩn cấp" mà chúng ta không phải lo lắng. Điều này có nghĩa là chúng ta vẫn có bốn trường hợp mà chúng ta có thể nghĩ đến mà không xem xét ba trường hợp khác trong hệ thống con khác và ngược lại. Nếu một số kết hợp phải được xác định đặc biệt và có thêm logic, thì lý do sẽ khó khăn hơn. Trong trường hợp xấu nhất, mọi sự kết hợp đều có một số xử lý đặc biệt, và sau đó thực sự có mười hai trường hợp mới, ngoài bốn và ba ban đầu.


0

Chắc chắn rồi. Đồng thời:

Các phần quan trọng được thi hành bởi mutexes: dễ hiểu vì chỉ có một nguyên tắc (hai luồng thực thi không thể vào phần quan trọng đồng thời), nhưng dễ bị kém hiệu quả và bế tắc.

Các mô hình thay thế, ví dụ như lập trình hoặc diễn viên không khóa: có khả năng thanh lịch và mạnh mẽ hơn nhiều, nhưng thật khó hiểu, bởi vì bạn không còn có thể dựa vào các khái niệm cơ bản (dường như) như "bây giờ hãy viết giá trị này đến nơi đó".

Dễ dàng lý luận là một khía cạnh của một phương pháp. Nhưng lựa chọn phương pháp nào để sử dụng đòi hỏi phải xem xét tất cả các khía cạnh kết hợp.


13
-1: ví dụ thực sự, thực sự tồi tệ khiến tôi nghĩ rằng bạn không hiểu cụm từ đó có nghĩa là gì. "Các phần quan trọng được thi hành bởi mutexes" trên thực tế là một trong những điều khó giải thích nhất ngoài kia - khá nhiều người sử dụng chúng đưa ra các điều kiện chủng tộc hoặc bế tắc. Tôi sẽ cung cấp cho bạn chương trình không khóa, nhưng toàn bộ điểm chết tiệt của mô hình diễn viên là nó dễ dàng hơn nhiều, lý do rất nhiều.
Michael Borgwardt

1
Vấn đề là đồng thời là một chủ đề rất khó để các lập trình viên suy luận, vì vậy nó không phải là một ví dụ hay. Bạn hoàn toàn chính xác rằng các phần quan trọng được thi hành bởi mutexes là một cách tương đối đơn giản để thực hiện đồng thời, so với lập trình không khóa, nhưng hầu hết các lập trình viên đều giống như Michael, và đôi mắt của họ sáng lên khi bạn bắt đầu nói về các phần quan trọng và đột biến, vì vậy điều này chắc chắn không có vẻ là một điều dễ hiểu. Chưa kể tất cả các lỗi.
Cody Grey

0

Hãy để chúng tôi giới hạn nhiệm vụ cho lý luận chính thức. Bởi vì lý luận hài hước hoặc phát minh hoặc thơ ca có luật khác nhau.

Mặc dù vậy, biểu thức được xác định mờ và không thể được đặt theo cách nghiêm ngặt. Nhưng nó không có nghĩa là nó vẫn còn quá mờ đối với chúng tôi. Chúng ta hãy tưởng tượng rằng một cấu trúc đang vượt qua một số bài kiểm tra và nhận được điểm cho các điểm khác nhau. Các điểm tốt cho MỌI điểm có nghĩa là cấu trúc thuận tiện ở mọi khía cạnh và do đó, "Dễ lý luận về".

Cấu trúc "Dễ lý luận về" sẽ đạt điểm cao cho các mục sau:

  • Các thuật ngữ bên trong có tên hợp lý, dễ dàng phân biệt và xác định. Nếu các phần tử có một số thứ bậc, sự khác biệt giữa tên cha và con nên khác với sự khác biệt giữa tên anh chị em.
  • Số loại yếu tố cấu trúc thấp
  • Các loại yếu tố cấu trúc được sử dụng là những thứ dễ dàng mà chúng ta đã quen thuộc.
  • Các yếu tố khó hiểu (thu hồi, bước meta, hình học 4 chiều ...) bị cô lập - không được kết hợp trực tiếp với nhau. . tùy thuộc vào n, bạn sẽ có một công thức riêng cho mỗi khối n và riêng biệt một quy tắc đệ quy cho công thức đó. Và hai cấu trúc riêng biệt có thể dễ dàng nghĩ ra)
  • Các loại yếu tố cấu trúc rõ ràng là khác nhau (ví dụ, không sử dụng mảng hỗn hợp bắt đầu từ 0 và từ 1)

Là bài kiểm tra chủ quan? Vâng, tự nhiên nó là. Nhưng bản thân biểu hiện cũng chủ quan. Điều gì là dễ dàng cho một người, không dễ dàng cho một người khác. Vì vậy, các bài kiểm tra nên khác nhau cho các lĩnh vực khác nhau.


0

Ý tưởng về các ngôn ngữ chức năng có thể suy luận xuất phát từ lịch sử của chúng, cụ thể là ML được phát triển như một ngôn ngữ lập trình tương tự như các cấu trúc mà Logic cho các hàm tính toán được sử dụng để suy luận. Hầu hết các ngôn ngữ chức năng gần với tính toán lập trình chính thức hơn các ngôn ngữ bắt buộc, do đó, việc dịch từ mã sang đầu vào của một hệ thống lý luận ít gặp khó khăn hơn.

Ví dụ về một hệ thống lý luận, trong phép tính pi, mỗi vị trí bộ nhớ có thể thay đổi trong một ngôn ngữ bắt buộc cần phải được biểu diễn dưới dạng một quá trình song song riêng biệt, trong khi một chuỗi các hoạt động chức năng là một quá trình đơn lẻ. Bốn mươi năm kể từ người ủng hộ định lý LFC, chúng tôi đang làm việc với GB RAM nên việc có hàng trăm quy trình là vấn đề ít hơn - Tôi đã sử dụng tính toán pi để loại bỏ các bế tắc tiềm năng từ vài trăm dòng C ++, mặc dù đại diện có hàng trăm xử lý lý do đã làm cạn kiệt không gian trạng thái trong khoảng 3 GB và khắc phục một lỗi không liên tục. Điều này sẽ là không thể vào những năm 70 hoặc cần một siêu máy tính vào đầu những năm 1990, trong khi không gian trạng thái của một chương trình ngôn ngữ chức năng có kích thước tương tự đủ nhỏ để lý giải về thời đó.

Từ các câu trả lời khác, cụm từ này đang trở thành một cụm từ buzz ngay cả khi phần lớn khó khăn khiến cho việc suy luận về các ngôn ngữ mệnh lệnh bị xói mòn bởi luật Moore.


-2

Dễ dàng lý luận là một thuật ngữ cụ thể về văn hóa, đó là lý do tại sao rất khó để đưa ra các ví dụ cụ thể. Đó là một thuật ngữ được neo vào những người sẽ làm lý luận.

"Dễ lý luận về" thực sự là một cụm từ rất tự mô tả. Nếu một người đang xem mã và muốn lý giải nó làm gì thì thật dễ dàng =)

Được rồi, phá vỡ nó. Nếu bạn đang xem mã, bạn thường muốn nó làm một cái gì đó. Bạn muốn chắc chắn rằng nó làm những gì bạn nghĩ nó nên làm. Vì vậy, bạn phát triển lý thuyết về những gì mã nên làm, và sau đó bạn lý do về nó để cố gắng tranh luận tại sao mã thực sự hoạt động. Bạn cố gắng nghĩ về mã như một con người (chứ không phải như một máy tính) và cố gắng hợp lý hóa các đối số về những gì mã có thể làm.

Trường hợp xấu nhất cho "dễ lý luận" là khi cách duy nhất để hiểu bất kỳ điều gì về mã là đi từng dòng thông qua mã như một máy Turing cho tất cả các đầu vào. Trong trường hợp này, cách duy nhất để suy luận bất cứ điều gì về mã là biến mình thành một máy tính và thực thi nó trong đầu. Những ví dụ tồi tệ nhất có thể dễ dàng nhìn thấy trong các cuộc thi lập trình bị lỗi thời, chẳng hạn như 3 dòng PERL này giải mã RSA:

#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)

Để dễ dàng lý luận, một lần nữa, thuật ngữ này có tính văn hóa cao. Bạn phải xem xét:

  • Người lý luận có những kỹ năng gì? Bao nhiêu kinh nghiệm?
  • Những loại câu hỏi mà lý do có thể có về mã?
  • làm thế nào chắc chắn các lý do cần phải được?

Mỗi trong số này ảnh hưởng đến "dễ lý luận về" khác nhau. Lấy các kỹ năng của lý luận làm ví dụ. Khi tôi bắt đầu tại công ty của mình, tôi khuyên bạn nên phát triển các tập lệnh của mình trong MATLAB vì nó "dễ lý do." Tại sao? Chà, mọi người trong công ty đều biết MATLAB. Nếu tôi chọn một ngôn ngữ khác, mọi người sẽ khó hiểu tôi hơn. Đừng bận tâm rằng khả năng đọc của MATLAB là tồi tệ đối với một số nhiệm vụ, đơn giản vì nó không được thiết kế cho chúng. Sau này, khi sự nghiệp của tôi phát triển, Python ngày càng trở nên phổ biến. Đột nhiên mã MATLAB trở nên "khó lý luận" và Python là ngôn ngữ ưu tiên để viết mã dễ lý do.

Cũng xem xét những gì idoms người đọc có thể có. Nếu bạn có thể dựa vào người đọc của mình để nhận ra một FFT theo một cú pháp cụ thể, thì "lý do dễ hiểu hơn" về mã nếu bạn tuân theo cú pháp đó. Nó cho phép họ xem tệp văn bản dưới dạng khung vẽ mà bạn đã vẽ FFT, thay vì phải đi vào các chi tiết ghê rợn. Nếu bạn đang sử dụng C ++, hãy tìm hiểu xem độc giả của bạn cảm thấy thoải mái với stdthư viện bao nhiêu. Họ thích lập trình chức năng bao nhiêu? Một số thành ngữ xuất phát từ các thư viện container phụ thuộc rất nhiều vào phong cách idomatic mà bạn thích.

Nó cũng quan trọng để hiểu những loại câu hỏi mà người đọc có thể quan tâm để trả lời. Có phải độc giả của bạn chủ yếu quan tâm đến sự hiểu biết hời hợt về mã, hoặc họ đang tìm kiếm các lỗi sâu trong ruột?

Làm thế nào chắc chắn người đọc phải thực sự là một trong những thú vị. Trong nhiều trường hợp, lý luận mơ hồ thực sự đủ để đưa sản phẩm ra khỏi cửa. Trong các trường hợp khác, chẳng hạn như phần mềm chuyến bay FAA, người đọc sẽ muốn có lý luận bằng sắt. Tôi gặp phải trường hợp tôi tranh luận về việc sử dụng RAII cho một nhiệm vụ cụ thể, bởi vì "Bạn có thể chỉ cần thiết lập và quên nó đi ... nó sẽ làm điều đúng đắn." Tôi đã nói rằng tôi đã sai về điều đó. Những người sẽ lý luận về mã này không phải là loại người "chỉ muốn quên đi các chi tiết." Đối với họ, RAII giống như một trò chơi treo cổ, buộc họ phải suy nghĩ về tất cả những điều có thể xảy ra khi bạn rời khỏi phạm vi.


12
Mã Perl khó đọc ; không lý do về. Nếu tôi có một số cổ phần trong việc phải hiểu nó, tôi sẽ làm mất mã. Mã thực sự khó lý luận là mã vẫn khó lý do khi nó được định dạng độc đáo với các định danh rõ ràng cho mọi thứ và không có thủ thuật đánh gôn.
Kaz
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.