Phá hoại các tiêu chuẩn mã hóa [đóng]


35

Có nhiều tiêu chuẩn mã hóa khác nhau được thi hành tại các công ty phần mềm với mục tiêu tăng độ tin cậy mã, tính di động và quan trọng nhất là khả năng đọc mã được viết bởi các nhà phát triển khác nhau.

Hai ví dụ đáng chú ý là MISRA C và tiêu chuẩn C ++ được phát triển cho dự án JSF .

Chúng thường ở dạng sau, sau khi chỉ định cẩn thận những từ "phải", "sẽ", "nên", "có thể", v.v. có nghĩa là:

Thí dụ:

Quy tắc 50: Các biến số dấu phẩy động sẽ không được kiểm tra về đẳng thức hoặc bất đẳng thức chính xác.

Đặt vấn đề: Vì số dấu phẩy động có thể bị lỗi làm tròn và cắt ngắn, nên có thể đạt được sự bằng nhau chính xác, ngay cả khi dự kiến.

Các tiêu chuẩn mã hóa này đặt ra các hạn chế, thường là về mã sẽ hợp pháp theo quan điểm của người biên soạn, nhưng nó nguy hiểm hoặc không thể đọc được, và do đó "được coi là có hại".

Bây giờ hãy lạm dụng điều này!

Bạn được chấp nhận là thành viên của một ủy ban tiêu chuẩn hóa nhỏ tại công ty của bạn, dự định thiết kế các tiêu chuẩn mã hóa mới mà mọi nhà phát triển tại công ty sẽ được yêu cầu sử dụng. Không biết đến những người khác, bạn đang bí mật thuê nhân viên của một tổ chức độc ác và có nhiệm vụ phá hoại công ty. Bạn phải đề xuất một hoặc nhiều mục nhập cho tiêu chuẩn mã hóa mà sau này sẽ cản trở các nhà phát triển. Tuy nhiên, bạn phải cẩn thận để không làm cho điều này rõ ràng ngay lập tức, nếu không bạn có nguy cơ nó không được chấp nhận vào tiêu chuẩn.

Nói cách khác, bạn phải đưa ra các quy tắc cho tiêu chuẩn mã hóa có vẻ hợp pháp và có cơ hội tốt để được các thành viên khác của ủy ban chấp nhận. Sau khi các dự án được bắt đầu và vô số giờ làm việc được đầu tư vào mã, bạn sẽ có thể lạm dụng các quy tắc này (ví dụ: bằng kỹ thuật hoặc rấtgiải nghĩa theo nghĩa đen) để đánh dấu mã khác bình thường và chất lượng tốt là trái với tiêu chuẩn. Vì vậy, họ phải nỗ lực rất nhiều để thiết kế lại nó và các quy tắc sẽ cản trở họ từ thời điểm này, nhưng vì các quy tắc đã hoạt động trong một thời gian khá lâu, động lực thuần túy sẽ giữ cho các vai trò này tồn tại và vì có những xung đột đáng kể về lợi ích giữa các cấp quản lý khác nhau, các nhà quản lý khác có thể sẽ giữ nguyên tắc sống (họ sẽ thật ngu ngốc khi thừa nhận sai lầm của mình!), do đó gây trở ngại cho công ty! Mwahahahahaaa!

Chấm điểm

Câu trả lời được bình chọn cao nhất sau khoảng 2 tuần kể từ lần nhập đầu tiên hợp lệ. Tôi có một ý tưởng cho một câu trả lời hay, nhưng tôi sẽ chỉ đăng nó vài ngày sau đó, vì người khác có thể có cùng ý tưởng, và tôi không muốn cướp chúng khỏi niềm vui. Tất nhiên, câu trả lời của riêng tôi sẽ không được chấp nhận trên bất kỳ câu hỏi nào khác, bất kể điểm số.

Các cử tri được khuyến khích chấm điểm các câu trả lời dựa trên mức độ sơ hở được ẩn giấu và mức độ bực bội đối với các nhà phát triển.

Các quy tắc và quy định

  • Các quy tắc hoặc quy tắc phải được viết chuyên nghiệp, như trong ví dụ trên
  • Các quy tắc phải trông thật (vì vậy những thứ như "tất cả các biến phải chứa ít nhất một dấu gạch dưới, một chữ in hoa, một chữ in thường và hai số" không được chấp nhận. Chúng thực sự sẽ cản trở các nhà phát triển, nhưng rất có thể sẽ không được chấp nhận bởi ủy ban) và nếu công đức của họ không rõ ràng ngay lập tức, bạn nên đưa ra một lý do tốt.
  • Bạn sẽ có thể tìm cách sử dụng / lạm dụng các quy tắc của mình để phá hoại các nhà phát triển sau này. Bạn có thể lạm dụng bất kỳ sự mơ hồ nào trong các quy tắc khác hoặc bạn có thể sử dụng nhiều quy tắc vô hại cho riêng mình, nhưng bệnh tiểu đường một khi được kết hợp!
  • Bạn nên đăng một lời giải thích trong các thẻ spoiler ở cuối bài viết của bạn về cách bạn có thể lạm dụng các quy tắc
  • Ngôn ngữ được sử dụng không được là ngôn ngữ bí truyền. Một ngôn ngữ được sử dụng rộng rãi trong các dự án thực tế phải được chọn, vì vậy các ngôn ngữ có cú pháp giống C (thay vì những thứ như Golfscript) được ưu tiên.

4
Python, Ruby, Haskell, Makefile, XML, v.v. là một số ngôn ngữ được sử dụng trong rất nhiều dự án thực tế không có cú pháp giống như C.
kennytm

7
Câu hỏi này dường như lạc đề vì đây không phải là một cuộc thi lập trình.
Peter Taylor

5
@PeterTaylor: định nghĩa bao gồm "Câu đố lập trình" không có nghĩa là câu trả lời phải là một đoạn mã phần mềm. Không nơi nào trong định nghĩa của trang web được viết rằng nó chỉ nói về "các cuộc thi lập trình". Định nghĩa là: "Mã golf / Câu đố lập trình / Các cuộc thi hoặc thử thách lập trình khác" "
vsz

7
@PeterTaylor có vẻ như một cuộc thi về lập trình với tôi; trong cảnh sát và kẻ cướp thách thức kẻ cướp cũng không mã hóa (và nếu lập luận của bạn là kẻ cướp bình luận, thì hãy chắc chắn nhận xét về bài đăng meta gợi ý chia tách cảnh sát và kẻ cướp cho hai câu hỏi riêng biệt)
John Dvorak

5
Tôi đã bỏ phiếu để mở lại. Có vẻ như chúng tôi vẫn còn một số câu hỏi mà chúng tôi không thể đồng ý về việc chúng có thuộc chủ đề hay không. Điều này nhắc nhở tôi về nghệ thuật liên quan đến nghệ thuật đã bị đóng cửa sau đó mở lại hai lần. Tôi có một ý tưởng cho một câu trả lời cho câu hỏi này và nó chắc chắn có liên quan đến lập trình. Câu hỏi này thậm chí phù hợp với 2 trong số các thẻ trên trang web.
hmatt1

Câu trả lời:


40

C / C ++

Quy tắc 1: hằng số bát phân không được sử dụng

Đặt vấn đề: hằng số bát phân có thể là một nguyên nhân gây nhầm lẫn. Ví dụ, một cái nhìn thoáng qua trên dòng const int coefficients[] = {132, 521, 013, 102};
có thể bỏ lỡ thực tế, rằng một trong các số trong mảng được xác định bằng số bát phân.

Nếu bạn muốn trở nên xấu xa hơn, hãy thêm vào như sau:

Quy tắc 2: hằng số thập lục phân chỉ được sử dụng trong bối cảnh thao tác bit.

Đặt vấn đề: Nếu một hằng đại diện cho một giá trị số, nó sẽ dễ đọc hơn nếu nó ở dạng thập phân. Hằng số thập lục phân phải chỉ ra rằng nó đại diện cho mặt nạ bit, không phải là giá trị số.

Làm thế nào nó có thể bị lạm dụng:

Thực hiện chương trình đơn giản sau đây sẽ thêm 10 phần tử đầu tiên của một mảng. Mã này sẽ không phù hợp với tiêu chuẩn.

sum = 0;
for (i = 0; i < 10; i++) 
{
    sum += array[i];
}

Lưu ý, đó 0là, theo định nghĩa, một hằng số bát phân. Theo quy tắc 1, yêu cầu nó phải được viết là 0x00 tất cả thông qua mã là bực bội. Theo quy tắc 2, thậm chí còn bực bội hơn.


1
Bạn có thể liên kết đến định nghĩa tiêu chuẩn mã hóa nói rằng đó 0là hằng số bát phân không? Tôi đoán rằng đó là vì nó bắt đầu bằng nhân vật 0. Nó sẽ củng cố lập luận của nhà sư phạm giả định của bạn.
xnor


16

Con trăn

Quy tắc 1: Tất cả các mã phải được biên dịch byte bằng cách sử dụng -OOcờ, giúp tối ưu hóa mã byte. Chúng tôi muốn tối ưu hóa mã byte cho kích thước và hiệu quả!

Quy tắc 2: Các thử nghiệm phải được chạy theo cùng một "tạo tác" của mã sẽ được đưa vào sản xuất. Kiểm toán viên của chúng tôi yêu cầu điều này.

Sử dụng -OOloại bỏassert báo cáo. Kết hợp với quy tắc 2, điều này cấm sử dụng hiệu quả các assertcâu lệnh trong các bài kiểm tra. Chúc vui vẻ!


Điều này cũng loại bỏ các tài liệu, nghĩa là bạn không nhận được bất cứ điều gì help()tại REPL và thử nghiệm REPL không chính thức vẫn đang thử nghiệm.
Kevin

Không. Nếu bạn viết một khung kiểm tra thích hợp, nó sẽ sử dụng unittestmô-đun hoặc mô-đun, thực hiện các xác nhận riêng của nó không phụ thuộc vào __debug__cờ. Tuy nhiên, Doctests sẽ không chạy. Lén lút!
pppery

15

Đây là một dự án Node.JS.

Phần 3 - Tốc độ và hiệu quả là điều cốt yếu

Quy tắc 3.1: Tệp phải được giữ ở mức tối đa 1kb. Các tệp lớn hơn này mất quá nhiều thời gian để phân tích.

Quy tắc 3.2: Không lồng chức năng sâu hơn 3 cấp. Động cơ V8 phải theo dõi nhiều biến số và việc đóng cửa sâu như thế này khiến nó hoạt động mạnh hơn, làm chậm quá trình giải thích chung.

Quy tắc 3.3: Tránhrequire() runaround.

Quy tắc 3.3.1: Bất kỳ mô-đun require()d nào không được require()sâu hơn 3. Sâurequire() Chuỗi đắt tiền cả về mức độ sử dụng bộ nhớ và tốc độ.

Quy tắc 3.3.2: Các mô-đun lõi được tính là một lần require(), bất kể chúng có bao nhiêu lần require()bên trong.

Quy tắc 3.3.3: Các mô-đun bên ngoài được tính tối đa là 2 require()s. Chúng tôi không thể đủ khả năng khoan hồng như với các mô-đun cốt lõi, nhưng có thể giả định rằng các tác giả mô-đun đang viết mã hiệu quả.

Quy tắc 3,4: Tránh các cuộc gọi đồng bộ bằng mọi giá. Việc này thường mất nhiều thời gian và chặn toàn bộ vòng lặp sự kiện tiếp tục.

Làm thế nào nó có thể bị lạm dụng:

Quy tắc 3.1 và 3.3 không hoạt động tốt với nhau. Bằng cách giữ tối đa 1kb và 3 require()giây trong chuỗi, họ sẽ khó có thể thành công.
Quy tắc 3.2 và 3.4 gần như không tương thích. 3,4 lệnh cấm cuộc gọi đồng bộ; 3.2 làm cho công việc không đồng bộ nâng cao trở nên khó khăn bằng cách giới hạn số lượng cuộc gọi lại.
Quy tắc 3,4 là, trong tất cả sự trung thực, một quy tắc tốt để tuân theo thực tế. 3.1, 3.2 và 3.3 là hoàn toàn không có thật.


11

JavaScript (Bản thảo)

7.3.2: Biểu thức chính quy

Chữ thường không được sử dụng. Cụ thể, mã nguồn không được chứa bất kỳ chuỗi phù hợp với các biểu thức chính quy không thuộc đầu cuối định nghĩa dưới đây.

RegularExpression     :: '/' RegularExpressionBody '/'
RegularExpressionBody :: [empty]
                         RegularExpressionBody [any-but-'/']

[trống] khớp với chuỗi trống và [any-but - '/'] khớp với bất kỳ chuỗi ký tự đơn nào ngoại trừ chuỗi có chứa '/' (dấu gạch chéo, U+002F).

Cơ sở lý luận

Biểu thức thông thường thường không được khuyến khích vì lý do dễ đọc. Nó thường dễ hiểu mã hơn với các hoạt động chuỗi truyền thống hơn là sử dụng các biểu thức thông thường. Quan trọng hơn, tuy nhiên, nhiều công cụ biểu thức chính quy cung cấp hiệu suất phụ. Các biểu thức chính quy cũng đã được liên kết với các vấn đề bảo mật trong ngữ cảnh của JavaScript.

Tuy nhiên, Tổ chức ™ nhận ra rằng các biểu thức thông thường đôi khi công cụ tốt nhất cho công việc. Do đó, RegExpbản thân đối tượng không bị cấm.

(Cú pháp của đoạn trích ngữ pháp [không phải là cú pháp do nó định nghĩa] tương ứng với cú pháp của đặc tả ECMAScript. Tất nhiên điều này sẽ được định nghĩa chặt chẽ hơn ở một điểm khác của đặc tả giả định.)

Bí quyết

Chương trình sau đây không tuân thủ:

// sgn(x) is -1 if x < 0, +1 if x > 0, and 0 if x = 0.
function sgn(x) {
  return x > 0?  +1
       : x < 0?  -1
       :          0
}

Các sản phẩm cho RegularExpressionBody không thuộc đầu cuối đưa ra ở trên các chương trình một cách phổ biến thể hiện danh sách trong BNF bằng cách dựa vào đệ quy rõ ràng. Bí quyết ở đây là tôi "vô tình" cho phép chuỗi rỗng như một RegularExpressionBody , chẳng hạn rằng chuỗi //bị cấm trong mã nguồn. Nhưng ai cần bình luận một dòng nào? C89 và CSS dường như làm tốt tất cả trong khi chỉ cho phép /* */chặn bình luận.


15
Nó thực sự thậm chí còn tệ hơn thế: mã có thể không chứa các bình luận khối, cũng không nhiều hơn một toán tử phân chia cho mỗi tệp.
Chromatix

Ồ vâng, bạn đúng. Tôi thậm chí không nghĩ về điều đó. : P
FireFly

5

C #

12.1 Các phương thức tĩnh ảnh hưởng đến trạng thái của chương trình đều bị cấm

Điều này là do khó có thể kiểm tra kết quả của một phương thức tĩnh, đặc biệt là một phương pháp thay đổi một số trạng thái.

12.2 Phương pháp tĩnh phải có tính xác định

Nếu phương thức tĩnh lấy một đầu vào và đưa ra một đầu ra thì kết quả phải giống nhau mỗi lần phương thức tĩnh được gọi với cùng một đầu vào.

Tại sao

Điểm vào cho chương trình C # là phương thức tĩnh riêng 'chính'. Theo quy tắc đầu tiên, điều này hiện bị cấm vì quy tắc quên nói rằng chỉ các phương thức công khai, được bảo vệ hoặc nội bộ mới tuân theo quy tắc này. Nếu kiểm thử thực sự là mối quan tâm thì chỉ có các phương thức công khai nên tuân theo quy tắc 1. Chính cũng có thể phá vỡ quy tắc 2 vì chương trình sẽ đưa ra mã lỗi nếu chương trình bị lỗi, điều này có thể xảy ra độc lập với các tham số đầu vào. Ví dụ, chương trình có thể không tìm thấy tệp hoặc có thể có phụ thuộc vào các hệ thống khác không được thiết lập chính xác.


4

JAVA / XUÂN

4.2 Sử dụng phản xạ trong mã sản xuất

Bởi vì Reflection có thể được sử dụng để truy cập các phần bị hạn chế khác trong việc sử dụng mã phản chiếu trong Mã sản xuất của chúng tôi bị nghiêm cấm.

Thủ thuật

Spring về mặt kỹ thuật sử dụng sự phản chiếu để khởi tạo và quản lý các đối tượng mà nó hỗ trợ. Bằng cách thực thi quy tắc này, tất cả tiện ích Spring sẽ phải được gỡ bỏ.


3

Mã hóa trang web

666.13 UTF-8 không được sử dụng và sẽ được thay thế bằng Cơ
sở lý luận UTF-7: UTF-7 hiệu quả hơn UTF-8, đặc biệt là khi nhắm mục tiêu người dùng từ các quốc gia Ả Rập mà chúng tôi làm.

Làm thế nào nó có thể bị lạm dụng:

HTML5 không cho phép UTF-7. Điều đó có nghĩa là, các trình duyệt hiện đại sẽ không hỗ trợ nó. Nếu tất cả các thử nghiệm được thực hiện trên một trình duyệt như IE 11, không ai sẽ nhận thấy điều này cho đến khi quá muộn.


2

Toán tử bitwise JavaScript

1.9 Bạn không được sử dụng phép nhân hoặc chia hoặc sàn trừ khi chúng nhanh hơn đáng kể so với các đối tác bitwise của chúng. Chúng sẽ được thay thế bởi các toán tử bitwise <<, >> và ~ ~ tương ứng.
Đặt vấn đề: Các toán tử bitwise hiệu quả hơn.

Làm thế nào nó có thể bị lạm dụng:

Sử dụng << hoặc >> thay vì nhân hoặc chia sẽ gây rắc rối khi xử lý số lượng lớn. Ngoài ra, họ bỏ qua ưu tiên hoạt động và điểm thập phân. Dấu ngã kép sẽ trả về các giá trị khác nhau khi bạn cho nó một số âm.


2
Tôi nghĩ rõ ràng x = (x<<10) + (x<<8) + (x<<5) + (x<<4) + (x<<3) + (x)là kém hơn về mọi mặt (thậm chí là tốc độ) x *= 1337, và việc thay thế sự phân chia bằng một sức mạnh không bằng hai bằng tổng số bithifts thậm chí còn tồi tệ hơn.
lirtosiast

@Thomas Kwa Tôi đã chỉnh sửa câu trả lời của mình một cách thích hợp. Cảm ơn bạn đã chỉ ra điều này. Tôi mới sử dụng toán tử bitwise.
Stefnotch

1

JavaScript (Bản thảo)

7.3.1: Quy ước định danh

Các hạn chế được đặt trên các định danh tùy thuộc vào loại định danh đó. Nhận dạng được chia thành các loại biến , liên tục , chức năngvị thi công ; xem 5.3. Các hạn chế được đưa ra dưới đây.

  • Biến: Ký tự đầu tiên phải là ký tự chữ thường. Trường hợp lạc đà (xem 1.3) nên được sử dụng để phân tách các từ trong một định danh.

  • Hằng số: Mã định danh phải chỉ bao gồm các ký tự chữ hoa và dấu gạch dưới ('_', U+005F). Dấu gạch dưới nên được sử dụng để phân tách các từ trong một định danh.

  • Chức năng: Các chức năng phải tuân theo các quy tắc giống như loại Định danh .

  • Người xây dựng: Ký tự đầu tiên phải là ký tự chữ hoa. Trường hợp lạc đà (xem 1.3) nên được sử dụng để phân tách các từ trong một định danh.

Cơ sở lý luận

Tên định danh dễ đọc là rất quan trọng đối với khả năng bảo trì. Việc hạn chế các định danh đối với các quy ước nổi tiếng cũng giúp giảm bớt sự chuyển đổi giữa các cơ sở mã khác nhau. Các quy ước cụ thể này được mô hình hóa theo các quy ước tiêu chuẩn cho ngôn ngữ lập trình Java ™ [1] .

Bí quyết

Tôi rất tiếc phải thông báo cho nhóm jQuery rằng tên phổ biến nhất cho "đối tượng jQuery toàn cầu" của họ xung đột với quy ước tên này. May mắn thay, họ đã nghĩ về điều đó và cung cấp cả hai $jQuerynhư các tên toàn cầu đề cập đến cùng một đối tượng. Tôi tưởng tượng rằng userbase có thể không được như mong muốn chuyển từ $đến jQuerykhắp mọi nơi, mặc dù.


2
»Các chức năng phải tuân theo các quy tắc giống như Mã định danh loại .« - ý bạn là »như loại Biến «?
Paŭlo Ebermann
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.