Tại sao nhà phát triển C # mới mở ngoặc? [đóng cửa]


44

Tôi đã dành hầu hết các năm qua làm việc chủ yếu với C # và SQL. Mọi lập trình viên mà tôi đã làm việc trong thời gian đó đều có thói quen đặt dấu ngoặc mở của hàm hoặc điều khiển luồng lệnh trên một dòng mới. Vì thế ...

public void MyFunction(string myArgument)
{
     //do stuff
}

if(myBoolean == true)
{
    //do something
}
else
{
    //do something else
}

Tôi luôn luôn bị ấn tượng bởi sự lãng phí không gian này, đặc biệt là trong các câu lệnh if / other. Và tôi biết các lựa chọn thay thế tồn tại trong các phiên bản sau của C #, như:

if(myBoolean == true)
    //do something on one line of code

Nhưng hầu như không ai sử dụng chúng. Mọi người đã làm điều xoăn-on-newline.

Sau đó tôi đã quay lại làm JavaScript sau một thời gian dài vắng bóng. Trong trí nhớ của tôi, các nhà phát triển JavaScript đã từng thực hiện chính xác cùng một thứ mới, nhưng với tất cả các thư viện và công cụ mới lạ mắt, hầu hết các nhà phát triển đều đặt dấu ngoặc mở sau khi khai báo:

function MyJavaScriptFunction() {
    //do something
}

Bạn có thể thấy ý nghĩa của việc này, bởi vì việc sử dụng các bao đóng và các con trỏ hàm đã trở nên phổ biến trong JavaScript, nó tiết kiệm rất nhiều không gian và làm cho mọi thứ dễ đọc hơn. Vì vậy, tôi đã tự hỏi tại sao nó không được xem là điều được thực hiện trong C #. Trên thực tế, nếu bạn thử cấu trúc trên trong Visual Studio 2013, nó thực sự định dạng lại nó cho bạn, đặt dấu ngoặc mở trên một dòng mới!

Bây giờ, tôi vừa thấy câu hỏi này trên Đánh giá mã SE: https://codereview.stackexchange.com/questions/48035/questions-responses-let-me-tell-you-about-you Trong đó tôi đã học được điều đó ở Java, a ngôn ngữ Tôi không quá quen thuộc, nó được coi là không nghiêm ngặt để mở dấu ngoặc nhọn của bạn ngay sau khi khai báo, theo kiểu JavaScript hiện đại.

Tôi đã luôn hiểu rằng C # ban đầu được mô hình hóa sau Java và được giữ theo nhiều tiêu chuẩn mã hóa cơ bản tương tự. Nhưng trong trường hợp này, có vẻ như không. Vì vậy, tôi cho rằng phải có một lý do chính đáng: lý do là gì? Tại sao các nhà phát triển C # (và Visual Studio) thực thi mở dấu ngoặc nhọn trên một dòng mới?


30
Công ước chỉ đơn giản là vậy.
Oded

19
Visual Studio thực thi không có gì, kiểu mã có thể cấu hình. Một cái gì đó cần phải được mặc định. Mà mặc định là "tốt hơn" là đi xe đạp của thứ tự cao nhất.
Phoshi

23
Nẹp ở cuối dòng là tiêu chuẩn K & R C cổ đại. Kernighan và Ritchie đã phát minh ra ngôn ngữ C khi màn hình máy tính chỉ có 25 dòng (23 nếu bạn thêm dòng tiêu đề và dòng trạng thái). Đó thực sự không phải là trường hợp nữa, phải không? Điều quan trọng là tính nhất quán trong suốt một dự án. cũng nghiên cứu khoa học cho thấy cú đúp trên một dòng riêng (thụt vào đến mức giống như mã số, trên thực tế) cải thiện đang hiểu mặc dù những gì mọi người nghĩ rằng họ nghĩ về tính thẩm mỹ.
Craig

10
Nhân tiện, C # luôn hỗ trợ đánh giá một dòng mã sau một điều kiện. Trên thực tế, đó là điều duy nhất nó làm, ngay cả bây giờ. Đặt mã trong dấu ngoặc nhọn sau một biểu thức phân nhánh chỉ làm cho lệnh đó trở thành một goto (trình biên dịch tạo phạm vi sử dụng các lệnh jmp). C ++, Java, C # và JavaScript đều ít nhiều dựa trên C, với hầu hết các quy tắc phân tích cú pháp cơ bản, đối với hầu hết các phần. Vì vậy, theo nghĩa đó, C # không "dựa trên Java."
Craig

10
Như một lưu ý phụ, if(myBoolean == true)làm cho rất ít ý nghĩa với tôi. Trong khi chúng ta đang ở đó, trong khi không if ((myBoolean == true) == true)?? Chỉ cần if (myBoolean)như vậy là đủ. Xin lỗi, một tiểu thú cưng của tôi.
Konrad Morawski

Câu trả lời:


67

Niềng răng ở cuối dòng là tiêu chuẩn K & R C cổ đại, từ cuốn sách Ngôn ngữ lập trình C của Brian Kernighan và Dennis Ritchie , mà họ đã xuất bản năm 1978 sau khi đồng phát minh ra hệ điều hành UNIX và ngôn ngữ lập trình C (tôi nghĩ C là chủ yếu được thiết kế bởi Ritchie), tại AT & T.

Đã từng có những cuộc chiến nảy lửa về "phong cách cú đúp thực sự".

Ritchie đã phát minh ra ngôn ngữ C và Kernighan đã viết hướng dẫn đầu tiên, khi màn hình máy tính chỉ hiển thị một vài dòng văn bản. Trên thực tế, sự phát triển của UNICS (sau này là UNIX) đã bắt đầu trên DEC PDP-7, sử dụng một máy đánh chữ, máy in và băng giấy cho giao diện người dùng. UNIX và C đã được hoàn thành trên PDP-11, với các thiết bị đầu cuối văn bản 24 dòng. Vì vậy, không gian dọc đã thực sự ở mức cao. Tất cả chúng ta đều có màn hình tốt hơn một chút và máy in độ phân giải cao hơn ngày hôm nay, phải không? Ý tôi là, tôi không biết về bạn, nhưng tôi có ba (3) màn hình 24 "1080p ngay trước mặt tôi :-)

Ngoài ra, rất nhiều cuốn sách nhỏ đó Ngôn ngữ lập trình C là các mẫu mã đặt dấu ngoặc ở cuối dòng thay vì trên dòng riêng của họ được cho là đã tiết kiệm một khoản tiền đáng kể khi in.

Điều thực sự quan trọng là tính nhất quán trong toàn bộ dự án hoặc ít nhất là trong một tệp mã nguồn đã cho.

cũng nghiên cứu khoa học cho thấy cú đúp trên một dòng riêng (thụt vào đến mức giống như mã số, trên thực tế) cải thiện đang hiểu mặc dù những gì mọi người nghĩ rằng họ nghĩ về tính thẩm mỹ. Nó làm cho nó rất rõ ràng cho người đọc, trực quan và bản năng, mã nào chạy trong bối cảnh nào.

if( true )
    {
    // do some stuff
    }

Nhân tiện, C # luôn hỗ trợ đánh giá một lệnh sau khi biểu thức phân nhánh. Trên thực tế, đó là điều duy nhất nó làm, ngay cả bây giờ. Đặt mã trong dấu ngoặc nhọn sau một biểu thức phân nhánh chỉ làm cho lệnh đó trở thành một goto (trình biên dịch tạo phạm vi sử dụng các lệnh jmp). C ++, Java, C # và JavaScript đều dựa trên C, với cùng một quy tắc phân tích cú pháp cơ bản, đối với hầu hết các phần. Vì vậy, theo nghĩa đó, C # không "dựa trên Java."

Tóm lại, đây một chút vấn đề tôn giáo / chiến tranh lửa. Nhưng có những nghiên cứu cho thấy khá rõ rằng việc sắp xếp mã theo khối giúp cải thiện sự hiểu biết của con người . Trình biên dịch không thể quan tâm ít hơn. Nhưng điều này cũng liên quan đến lý do tại sao tôi không bao giờ đặt một dòng mã sau một nhánh mà không có dấu ngoặc - thật dễ dàng cho tôi hoặc một lập trình viên khác để đặt một dòng mã khác vào đó sau đó và thực tế là nó sẽ không thực hiện trong cùng một bối cảnh với dòng ngay trước hoặc sau nó.

EDIT : Chỉ cần nhìn vào lỗi của Applegoto fail để biết một ví dụ hoàn hảo về vấn đề chính xác này, nó đã gây ra hậu quả rất nghiêm trọng trong thế giới thực.

if( true )
    doSomething();

trở thành ...

if( true )
    doSomething();
    doSomethingElse();

Trong trường hợp này, doSomethingElse()thực thi mọi lúc, bất kể kết quả của bài kiểm tra, nhưng vì nó được thụt vào cùng mức với doSomething()câu lệnh, nên rất dễ bỏ lỡ. Điều này thực sự không thể tranh cãi; nghiên cứu trở lại này lên. Đây là một nguồn lớn các lỗi được đưa vào mã nguồn trong quá trình bảo trì.

Tuy nhiên, tôi sẽ thừa nhận rằng cú pháp đóng JavaScript trông hơi ngớ ngẩn với các dấu ngoặc trên các dòng riêng của chúng ... về mặt thẩm mỹ. :-)


13
Phần về các khối trong điều kiện là hơi sai lệch. Trong C, điều kiện luôn có một câu lệnh đơn, nhưng một khối (hay còn gọi là câu lệnh ghép) là một loại câu lệnh . C # tuân theo tiền lệ này. Dù sao, đánh giá có điều kiện luôn bao hàm một số loại lệnh goto hoặc phân nhánh có điều kiện, do tính chất tuyến tính của tất cả các tập lệnh phổ biến. Một điều kiện không có khối không khác biệt về chất với điều kiện có khối (ngoại trừ liên quan đến phạm vi).
amon

3
@Craig, hãy nhớ rằng, đây là tại Bell Labs, trở lại khi Bell Labs được thuê để "làm những việc thú vị" mà không nhất thiết phải thực tế cho bất cứ điều gì. Đặt những người thông minh vào một tòa nhà, bảo họ thực hiện một số nghiên cứu thú vị, đưa họ ra khỏi những gì họ làm không "thú vị", và điều thú vị là những thứ QUAN TÂM (như bóng bán dẫn và Unix) có xu hướng bật ra. DARPA đã có cùng một trọng tâm, ngay từ đầu, và họ đã tài trợ RẤT NHIỀU công việc tốt, nhân danh nghiên cứu cơ bản.
John R. Strohm

3
@Craig: Trong những ngày Pascal / Delphi cũ, tôi thường tránh nó cho các khối đơn dòng, như sử dụng Pascal beginendở vị trí của niềng răng, mà làm cho các lỗi như vậy thật khó để bỏ lỡ, và nó cũng chặt chẽ hơn về vị trí dấu chấm phẩy - nhưng có chi phí 4 ngày năm ngoái gỡ lỗi một vấn đề trong nhúng C mà kết quả là do thiếu vị trí niềng răng của ai đó ..... Tôi nghĩ rằng nên có một tùy chọn trình biên dịch khiến cho dấu ngoặc nhọn bắt buộc cho các câu lệnh điều khiển!
Mark K Cowan

12
Vui lòng cung cấp tài liệu tham khảo cho "... các nghiên cứu khoa học cho thấy rằng niềng răng trên dây chuyền của chính nó ...". Không có ít nhất hai tài liệu tham khảo (nếu không sẽ là nghiên cứu , không phải nghiên cứu ), nó chỉ bắn ngẫu nhiên vào không trung.
ErikE

2
@Craig, bạn có thể cung cấp một số manh mối làm thế nào để tìm những nghiên cứu mà bạn đề cập không?
Grzegorz Adam Kowalski

30

Lý do các nhà phát triển C # làm điều đó là vì đó là cài đặt mặc định của trình định dạng tự động Visual Studio. Mặc dù cài đặt này có thể được thay đổi, nhưng hầu hết mọi người đều không, và do đó, tất cả các nhà phát triển trong một nhóm phải đi theo đa số.

Về lý do tại sao đây là mặc định trong Visual Studio, tôi không biết.


15
Đây là mặc định trong Visual Studio bởi vì đó là phong cách mã hóa được chấp nhận rộng rãi tại Microsoft, cách trở lại và trên thực tế, ít nhất một số nhóm tại Microsoft, phong cách này không chỉ là niềng răng trên các dòng riêng của họ, mà là niềng răng trên các dòng riêng của họ và thụt lề. Vì vậy, đó cũng là một tùy chọn trong Visual Studio (cá nhân tôi thích nó).
Craig

20

5
@PreferenceBean Hmm. Cá nhân tôi không thích phong cách K & R, vì các dấu ngoặc chỉ bị mất tiếng ồn ở cuối dòng và văn bản trông có vẻ lộn xộn đối với tôi, không chỉ là một sở thích thẩm mỹ, mà có tác động thực sự đến khả năng đọc / hiểu. Tôi thích khoảng trắng dọc. Nó có một chút khác biệt trên màn hình 12 "với 24 dòng văn bản trở lại vào thời xưa khi không gian dọc là quý giá.
Craig

10
@Craig: Đó không phải là lý do để thụt niềng răng: P
Cuộc đua ánh sáng với Monica

2
@Craig Để làm cho nhân viên của Microsoft khốn khổ?
Mateen Ulhaq

18

Như tôi đã đưa ra giả thuyết trong câu trả lời này tại đây - https://softwareengineering.stackexchange.com/a/159081/29029 - Tôi cho rằng quyết định đi với niềng răng của Allman có thể là một dấu hiệu của di sản Pascal, vì Hejlsberg đã tạo ra Delphi trước khi anh ta thiết kế C # . Tương tự như trường hợp Pascal cho tên phương thức.

Cá nhân tôi tin rằng theo câu ngạn ngữ "ở Rome làm như người La Mã làm". Tôi sử dụng Allman trong C #, nhưng K & R trong Java. Tôi đã quá quen với việc chuyển đổi quy ước theo bất kỳ cách nào cũng làm tôi chói tai.

Tôi tin rằng một số đa dạng hội nghị thực sự có lợi cho nhà phát triển "đa ngôn ngữ" vì nó giúp ghi nhớ ngôn ngữ mà họ đang mã hóa vào lúc này và giúp dễ dàng phân biệt các thói quen khác nhau. Đó là một tương đương tinh thần của bộ nhớ cơ bắp, để nói.


7
+1 cho dòng "nhà phát triển đa ngôn ngữ", thực sự. Tôi thực sự thích niềng răng trên đường riêng và thụt vào. Tuy nhiên, trong quá trình làm việc, ví dụ, các dự án ASP.NET (MVC), tôi thấy rằng tôi thích C # với kiểu "đúng" và JavaScript với kiểu "JavaScript". Đó là một câu nói nhỏ, nhưng thành thật mà nói, đó là cú pháp đóng của JavaScript hấp dẫn hơn với dấu ngoặc ở cuối dòng. Vì vậy, tôi cũng là nô lệ cho thẩm mỹ như bất kỳ ai khác ...
Craig

PascalCase cho tên phương thức là một tiêu chuẩn tại Microsoft một thời gian dài trước khi Anders Hejlsberg rời Borland để trở thành một kỹ sư phần mềm nổi tiếng tại Microsoft.
Craig

2
Thật thú vị, tôi sử dụng Allman cho tất cả các ngôn ngữ chặn. Tuy nhiên, tôi ngày càng quan tâm đến việc chuyển đổi tiền xử lý các vết lõm thành các khối giằng xoăn có thể trông như thế nào trong Java. Mã "java" có thể trông cực kỳ sạch sẽ, một khi tôi quấn lấy tâm trí nhận dạng mẫu của mình xung quanh nó. Tôi nghĩ Python thực sự có thể có quyền: Thực sự không có lý do tuyệt vời nào cho việc niềng răng bằng ngôn ngữ.
tgm1024

Sử dụng khoảng trắng để kiểm soát luồng chương trình là sự điên rồ. Python là phổ biến ngày nay, nhưng khía cạnh này của Python đã có một chút điên rồ kể từ khi nó xuất hiện lần đầu tiên.
Craig

@Craig Người hâm mộ Python ở đây, cố gắng hoàn thành một cái gì đó trong javascript. Nhìn vào câu trả lời khác của bạn và chỉnh sửa của bạn về việc goto failsử dụng thụt lề để kiểm soát luồng chương trình là điều con người tự nhiên muốn làm, vì vậy những gì bạn thấy là những gì thực thi. Nếu nó thụt lề sai, nó không hoạt động. Phải giải mã ý nghĩa của những cái niềng răng đó, cho dù chúng thực sự phản ánh vết lõm, là công việc bổ sung hơn và hơn là hiểu chương trình. Lõm là dư thừa cho niềng răng, vậy tại sao các lập trình viên sử dụng nó nếu niềng răng là hữu ích? Làm tổ sâu là không thể hiểu được trong bất kỳ ngôn ngữ. Jus 'sayin'.
Neil_UK

14

Quy ước mà bạn liên kết với Java là kiểu K & R hoặc "Một kiểu niềng răng thực sự" và có nguồn gốc từ C. Trang này theo kiểu thụt lề từ Tệp Jargon đáng kính cho thấy mức độ khác biệt của nó.

Tôi đã luôn nghĩ rằng kiểu Allman và các biến thể của nó là sự phản ánh cách các tác giả nghĩ về mã, nâng các dấu phân cách khối lên mức từ khóa tương tự như cách một số ngôn ngữ sử dụng "bắt đầu" và "kết thúc" xung quanh các khối mã.


Tôi có ấn tượng rằng những ngày này OTBS (một kiểu niềng răng thực sự) cũng ngụ ý không bao giờ rời khỏi dấu ngoặc sau các câu lệnh điều khiển, ngay cả đối với các dòng mã. Xem lỗi Apple goto fail.
Craig
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.