Tại điểm nào là ngắn gọn không còn là một đức tính?


102

Một bản sửa lỗi gần đây yêu cầu tôi chuyển qua mã được viết bởi các thành viên khác trong nhóm, nơi tôi đã tìm thấy mã này (đó là C #):

return (decimal)CostIn > 0 && CostOut > 0 ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 : 0;

Bây giờ, cho phép có một lý do chính đáng cho tất cả các diễn viên đó, điều này dường như vẫn rất khó theo dõi. Có một lỗi nhỏ trong tính toán và tôi đã phải gỡ rối nó để khắc phục vấn đề.

Tôi biết phong cách mã hóa của người này từ đánh giá mã, và cách tiếp cận của anh ta là ngắn hơn hầu như luôn luôn tốt hơn. Và tất nhiên có giá trị ở đó: tất cả chúng ta đã thấy các chuỗi logic có điều kiện phức tạp không cần thiết có thể được làm sạch với một vài toán tử được đặt tốt. Nhưng rõ ràng anh ta lão luyện hơn tôi khi theo các chuỗi nhà điều hành nhồi nhét vào một tuyên bố duy nhất.

Tất nhiên, đây là vấn đề của phong cách. Nhưng có bất cứ điều gì đã được viết hoặc nghiên cứu để nhận ra điểm mà việc phấn đấu cho mã ngắn không còn hữu ích và trở thành rào cản đối với sự hiểu biết?

Lý do cho các diễn viên là Entity Framework. Các db cần lưu trữ chúng dưới dạng nullable. Số thập phân? không tương đương với số thập phân trong C # và cần được bỏ.


153
Khi vấp ngã dễ đọc.
Robert Harvey

27
Nhìn vào ví dụ cụ thể của bạn: một diễn viên là (1) một nơi mà nhà phát triển biết nhiều hơn trình biên dịch và cần cho trình biên dịch biết một thực tế không thể suy ra, hoặc (2) trong đó một số dữ liệu được lưu trữ trong "sai "Loại cho các loại hoạt động chúng ta cần thực hiện trên đó. Cả hai đều là những chỉ số mạnh mẽ mà một cái gì đó có thể được tái cấu trúc. Giải pháp tốt nhất ở đây là tìm cách viết mã không có phôi.
Eric Lippert

29
Cụ thể, có vẻ kỳ quái là cần phải sử dụng CostIn thành thập phân để so sánh nó với 0, nhưng không phải CostOut; tại sao vậy? Cái gì trên trái đất là loại CostIn mà nó chỉ có thể được so sánh với số 0 bằng cách chuyển nó thành số thập phân? Và tại sao CostOut không cùng loại với CostIn?
Eric Lippert

12
Hơn nữa, logic ở đây thực sự có thể sai. Giả sử CostOutbằng Double.Epsilon, và do đó lớn hơn 0. Nhưng (decimal)CostOuttrong trường hợp đó là 0, và chúng ta có một phép chia cho số không. Bước đầu tiên là lấy mã chính xác , điều mà tôi nghĩ là không phải. Làm cho nó chính xác, làm cho các trường hợp thử nghiệm, và sau đó làm cho nó thanh lịch . Mã thanh lịch và mã ngắn gọn có rất nhiều điểm chung, nhưng đôi khi sự ngắn gọn không phải là linh hồn của sự thanh lịch.
Eric Lippert

5
Brevity luôn là một đức tính tốt. Nhưng chức năng mục tiêu của chúng tôi kết hợp sự ngắn gọn với các đức tính khác. Nếu một người có thể mạnh mẽ hơn mà không làm tổn hại đến các đức tính khác, người ta luôn luôn nên.
Bí mật của Solomonoff

Câu trả lời:


163

Để trả lời câu hỏi của bạn về nghiên cứu còn tồn tại

Nhưng có bất cứ điều gì đã được viết hoặc nghiên cứu để nhận ra điểm mà việc phấn đấu cho mã ngắn không còn hữu ích và trở thành rào cản đối với sự hiểu biết?

Vâng, đã có công việc trong lĩnh vực này.

Để hiểu được công cụ này, bạn phải tìm cách tính toán một số liệu để có thể so sánh trên cơ sở định lượng (thay vì chỉ thực hiện so sánh dựa trên trí thông minh và trực giác, như các câu trả lời khác làm). Một số liệu tiềm năng đã được xem xét là

Độ phức tạp theo chu kỳ Các dòng mã nguồn ( SLOC )

Trong ví dụ mã của bạn, tỷ lệ này rất cao, vì mọi thứ đã được nén trên một dòng.

SATC đã tìm thấy sự đánh giá hiệu quả nhất là sự kết hợp giữa kích thước và độ phức tạp [Cyclomatic]. Các mô-đun với cả độ phức tạp cao và kích thước lớn thường có độ tin cậy thấp nhất. Các mô-đun với kích thước thấp và độ phức tạp cao cũng là một rủi ro về độ tin cậy bởi vì chúng có xu hướng rất mã, rất khó thay đổi hoặc sửa đổi.

Liên kết

Dưới đây là một vài tài liệu tham khảo nếu bạn quan tâm:

McCabe, T. và A. Watson (1994), Độ phức tạp phần mềm (CrossTalk: Tạp chí Kỹ thuật phần mềm quốc phòng).

Watson, AH, & McCabe, TJ (1996). Kiểm tra có cấu trúc: Một phương pháp thử nghiệm sử dụng thước đo độ phức tạp theo chu kỳ (Ấn phẩm đặc biệt NIST 500-235). Truy cập ngày 14 tháng 5 năm 2011, từ trang web của McCabe Software: http://www.mccabe.com/pdf/mccabe-nist235r.pdf

Rosenberg, L., Búa, T., Shaw, J. (1998). Số liệu và độ tin cậy của phần mềm (Kỷ yếu của Hội thảo quốc tế về kỹ thuật độ tin cậy của phần mềm). Truy cập ngày 14 tháng 5 năm 2011, từ trang web của Đại học bang Pennsylvania: http://citeseerx.ist.psu.edu/viewdoc/doad?doi=10.1.1.104.4041&rep=rep1&type=pdf

Ý kiến ​​và giải pháp của tôi

Cá nhân, tôi chưa bao giờ coi trọng sự ngắn gọn, chỉ có thể đọc được. Đôi khi sự ngắn gọn giúp dễ đọc, đôi khi không. Điều quan trọng hơn là bạn đang viết Mã thực sự rõ ràng (ROC) thay vì Mã chỉ viết (WOC).

Để cho vui, đây là cách tôi sẽ viết nó và yêu cầu các thành viên trong nhóm của tôi viết nó:

if ((costIn <= 0) || (costOut <= 0)) return 0;
decimal changeAmount = costOut - costIn;
decimal changePercent = changeAmount / costOut * 100;
return changePercent;

Cũng lưu ý rằng việc giới thiệu các biến làm việc có tác dụng phụ hạnh phúc là kích hoạt số học điểm cố định thay vì số học số nguyên, do đó, cần phải decimalloại bỏ tất cả các phôi đó .


4
Tôi thực sự thích mệnh đề bảo vệ cho trường hợp ít hơn không. Có thể xứng đáng nhận xét: làm thế nào một chi phí có thể nhỏ hơn 0, trường hợp đặc biệt đó là gì?
dùng949300

22
+1. Tôi có thể sẽ thêm một cái gì đó nhưif ((costIn < 0) || (costOut < 0)) throw new Exception("costs must not be negative");
Doc Brown

13
@DocBrown: Đó là một gợi ý hay, nhưng tôi sẽ xem xét liệu đường dẫn mã đặc biệt có thể được thực hiện bằng thử nghiệm hay không. Nếu có, sau đó viết một trường hợp thử nghiệm thực hiện mã đường dẫn đó. Nếu không, sau đó thay đổi toàn bộ thành một khẳng định.
Eric Lippert

12
Mặc dù đây đều là những điểm tốt, tôi tin rằng phạm vi của câu hỏi này là, kiểu mã chứ không phải logic. Snip mã của tôi là một nỗ lực tương đương chức năng từ quan điểm hộp đen. Ném một ngoại lệ không giống như trả về 0, do đó giải pháp đó sẽ không tương đương về mặt chức năng.
John Wu

30
"Cá nhân tôi, tôi chưa bao giờ coi trọng sự ngắn gọn, chỉ có thể đọc được. Đôi khi sự ngắn gọn giúp dễ đọc, đôi khi không." Điểm tuyệt vời . +1 chỉ cho điều đó. Tôi thích giải pháp mã của bạn, quá.
tự đại diện

49

Brevity là tốt khi nó làm giảm sự lộn xộn xung quanh những thứ quan trọng, nhưng khi nó trở nên ngắn gọn , việc đóng gói quá nhiều dữ liệu liên quan quá dày đặc để dễ dàng theo dõi, thì dữ liệu liên quan sẽ trở nên lộn xộn và bạn gặp vấn đề.

Trong trường hợp cụ thể này, các diễn viên decimalsẽ được lặp đi lặp lại nhiều lần; có lẽ sẽ tốt hơn nếu viết lại nó như một cái gì đó như:

var decIn = (decimal)CostIn;
var decOut = (decimal)CostOut;
return decIn > 0 && CostOut > 0 ? (decOut - decIn ) / decOut * 100 : 0;
//                  ^ as in the question

Đột nhiên, dòng chứa logic ngắn hơn rất nhiều và nằm trên một đường ngang, do đó bạn có thể nhìn thấy mọi thứ mà không cần phải cuộn, và ý nghĩa dễ thấy hơn nhiều.


1
Tôi có lẽ đã đi xa hơn và tái cấu trúc ((decOut - decIn ) / decOut) * 100sang một biến khác.
Thất vọngWithFormsDesigner

9
Trình biên dịch đã rõ ràng hơn nhiều: chỉ một thao tác trên mỗi dòng. Đừng!

2
@FrustratedWithFormsDesigner Tôi thậm chí sẽ tiến thêm một bước và bọc kiểm tra có điều kiện trong ngoặc đơn.
Chris Cirefice

1
@FrustratedWithFormsDesigner: Trích xuất điều này trước khi có điều kiện sẽ bỏ qua kiểm tra divison-by-zero ( CostOut > 0), vì vậy bạn phải mở rộng điều kiện thành một if-statement. Không có gì sai với điều này, nhưng nó làm tăng thêm tính dài dòng hơn là việc giới thiệu một địa phương.
wchargein

1
Thành thật mà nói, việc loại bỏ các diễn viên có vẻ giống như bạn đã phát sóng IMO đủ, nếu ai đó khó đọc vì anh ta không thể nhận ra một phép tính tỷ lệ cơ bản đơn giản, đó là vấn đề của anh ta, không phải của tôi.
Walfrat

7

Mặc dù tôi không thể trích dẫn bất kỳ nghiên cứu cụ thể nào về chủ đề này, tôi sẽ đề nghị rằng tất cả các diễn viên trong mã của bạn đều vi phạm nguyên tắc Đừng lặp lại chính mình. Những gì mã của bạn dường như đang cố gắng làm là chuyển đổi costIncostOutnhập Decimal, sau đó thực hiện một số kiểm tra độ tỉnh táo đối với kết quả của các chuyển đổi đó và thực hiện các thao tác bổ sung trên các giá trị được chuyển đổi đó nếu kiểm tra vượt qua. Trong thực tế, mã của bạn thực hiện một trong những kiểm tra độ tỉnh táo đối với giá trị chưa được chuyển đổi, làm tăng khả năng costOut có thể giữ giá trị lớn hơn 0, nhưng nhỏ hơn một nửa so với giá trị nhỏ nhất Decimalcó thể biểu thị. Mã sẽ rõ ràng hơn nhiều nếu nó xác định các biến loại Decimalđể giữ các giá trị được chuyển đổi, và sau đó hành động theo các giá trị đó.

Có vẻ như tò mò rằng bạn sẽ quan tâm nhiều hơn đến tỷ lệ của các Decimalđại diện costIncostOuthơn tỷ lệ của các giá trị thực tế costIncostOut, trừ khi mã cũng sẽ sử dụng các biểu diễn thập phân cho một số mục đích khác. Nếu mã sẽ sử dụng thêm các biểu diễn đó, thì đó sẽ là đối số tiếp theo để tạo các biến để giữ các biểu diễn đó, thay vì có một chuỗi các diễn viên tiếp tục trong suốt mã.


Các phôi (thập phân) có thể là để đáp ứng một số yêu cầu quy tắc kinh doanh. Khi giao dịch với kế toán đôi khi bạn phải nhảy qua những cái vòng ngu ngốc. Tôi nghĩ rằng CFO sẽ bị đau tim khi anh ta tìm thấy dòng "Sử dụng hiệu chỉnh vòng thuế - $ 0,01" không thể tránh khỏi với chức năng được yêu cầu. (Được cung cấp: Giá sau thuế. Tôi phải tính giá trước thuế. Tỷ lệ cược sẽ không có câu trả lời bằng với thuế suất.)
Loren Pechtel

@LorenPechtel: Cho rằng độ chính xác mà Decimaldiễn viên sẽ làm tròn phụ thuộc vào độ lớn của giá trị được đề cập, tôi thấy khó có thể tưởng tượng các quy tắc kinh doanh sẽ gọi theo cách các diễn viên thực sự sẽ hành xử.
supercat

1
Điểm hay - Tôi đã quên các chi tiết của loại thập phân vì tôi chưa bao giờ có dịp muốn một cái gì đó giống như vậy. Bây giờ tôi nghĩ rằng đây là sự tôn trọng hàng hóa tuân theo các quy tắc kinh doanh - cụ thể, tiền không phải là điểm nổi.
Loren Pechtel

1
@LorenPechtel: Để làm rõ điểm cuối cùng của tôi: một loại điểm cố định có thể đảm bảo rằng x + yy sẽ tràn hoặc mang lại y. Các Decimalloại không. Giá trị 1.0d / 3.0 sẽ có nhiều chữ số ở bên phải của số thập phân hơn mức có thể được duy trì khi sử dụng số lớn hơn. Vì vậy, thêm và sau đó trừ cùng một số lớn hơn sẽ gây ra mất độ chính xác. Các loại điểm cố định có thể mất độ chính xác với phép nhân hoặc phép chia phân số, nhưng không có phép cộng, phép trừ, phép nhân hoặc phép chia với phần dư (ví dụ: 1,00 / 7 là 0,14 phần còn lại 0,2; 1,00 div 0,15 là 6 phần còn lại 0,10).
supercat

1
@ Hulk: Vâng, tất nhiên. Tôi đang tranh luận về việc nên sử dụng x + yy mang lại x, x + yx mang lại y, hay x + yxy, và cuối cùng đã kết thúc sai lầm trong hai lần đầu tiên. Điều quan trọng là các loại điểm cố định có thể đảm bảo rằng nhiều chuỗi hoạt động sẽ không bao giờ gây ra các lỗi làm tròn không bị phát hiện ở bất kỳ cường độ nào . Nếu mã cộng các thứ lại với nhau theo các cách khác nhau để xác minh rằng tổng số khớp với nhau (ví dụ: so sánh tổng của tổng phụ hàng với tổng của tổng phụ cột), thì kết quả đưa ra chính xác bằng nhau sẽ tốt hơn nhiều so với việc chúng xuất hiện "đóng".
supercat

5

Tôi nhìn vào mã đó và hỏi "làm thế nào chi phí có thể bằng 0 (hoặc ít hơn)?". Trường hợp đặc biệt nào chỉ ra? Mã phải

bool BothCostsAreValidProducts = (CostIn > 0) && (CostOut > 0);
if (!BothCostsAreValidProducts)
  return NO_PROFIT;
else {
   // that calculation here...
}

Tôi đoán là đặt tên ở đây: thay đổi BothCostsAreValidProductsNO_PROFITphù hợp.


Tất nhiên, chi phí có thể bằng không (nghĩ rằng quà tặng Xmas). Và trong thời điểm lãi suất âm, chi phí âm cũng không quá đáng ngạc nhiên và ít nhất mã phải được chuẩn bị để đối phó với nó (và có thể bằng cách ném lỗi)
Hagen von Eitzen

Bạn đang đi đúng hướng.
danny117

Điều đó thật ngớ ngẩn. if (CostIn <= 0 || CostOut <= 0)là hoàn toàn tốt
Miles Rout

Ít đọc hơn nhiều. Tên biến là khủng khiếp (BothCostsAreValid sẽ tốt hơn. Không có gì ở đây về sản phẩm). Nhưng ngay cả điều đó không thêm bất cứ điều gì vào khả năng đọc, bởi vì chỉ cần kiểm tra CostIn, CostOut là ổn. Bạn sẽ giới thiệu một biến phụ có tên có ý nghĩa nếu ý nghĩa của biểu thức đang được kiểm tra là không rõ ràng.
gnasher729

5

Brevity ngừng là một đức tính khi chúng ta quên nó có nghĩa là kết thúc chứ không phải là một đức tính trong chính nó. Chúng tôi thích sự ngắn gọn vì nó tương quan với sự đơn giản và chúng tôi thích sự đơn giản vì mã đơn giản dễ hiểu hơn và dễ sửa đổi hơn và chứa ít lỗi hơn. Cuối cùng, chúng tôi muốn mã để đạt được các mục tiêu này:

  1. Hoàn thành các yêu cầu kinh doanh với số lượng công việc ít nhất

  2. Tránh lỗi

  3. Cho phép chúng tôi thực hiện các thay đổi trong tương lai tiếp tục thực hiện 1 và 2

Đây là những mục tiêu. Bất kỳ nguyên tắc hoặc phương pháp thiết kế nào (có thể là KISS, YAGNI, TDD, RẮN, bằng chứng, hệ thống loại, siêu lập trình động, v.v.) chỉ có đạo đức trong phạm vi chúng giúp chúng ta đạt được những mục tiêu này.

Các dòng trong câu hỏi dường như đã bỏ lỡ tầm nhìn của mục tiêu cuối cùng. Trong khi nó ngắn, nó không đơn giản. Nó thực sự chứa sự dư thừa không cần thiết bằng cách lặp lại cùng một thao tác đúc nhiều lần. Lặp lại mã làm tăng sự phức tạp và khả năng xảy ra lỗi. Kết hợp việc đúc với tính toán thực tế cũng làm cho mã khó theo dõi.

Dòng này có ba mối quan tâm: Bảo vệ (vỏ đặc biệt 0), loại đúc và tính toán. Mỗi mối quan tâm là khá đơn giản khi được thực hiện trong sự cô lập, nhưng vì tất cả đã được xen kẽ trong cùng một biểu thức, nó trở nên khó theo dõi.

Không rõ tại sao CostOutlần đầu tiên nó không được sử dụng CostIn. Có thể có một lý do chính đáng, nhưng ý định không rõ ràng (ít nhất là không có ngữ cảnh), điều đó có nghĩa là một người bảo trì sẽ cảnh giác khi thay đổi mã này bởi vì có thể có một số giả định ẩn. Và đây là sự vô cảm đối với khả năng duy trì.

CostInđược truyền trước khi so sánh với 0 nên tôi giả sử đó là giá trị dấu phẩy động. (Nếu đó là một int thì sẽ không có lý do để phân vai). Nhưng nếu CostOutlà số float thì mã có thể ẩn một lỗi chia nhỏ không rõ ràng, vì giá trị dấu phẩy động có thể nhỏ nhưng khác không, nhưng bằng 0 khi chuyển thành số thập phân (ít nhất tôi tin rằng điều này có thể xảy ra.)

Vì vậy, vấn đề không phải là ngắn gọn hay thiếu nó, vấn đề là logic lặp đi lặp lại và sự kết hợp các mối quan tâm dẫn đến mã khó duy trì.

Việc đưa ra các biến để giữ các giá trị được đúc có thể sẽ tăng kích thước mã được tính theo số lượng mã thông báo, nhưng sẽ làm giảm độ phức tạp, các mối quan tâm riêng biệt và cải thiện độ rõ ràng, giúp chúng ta đến gần hơn với mục tiêu mã dễ hiểu và duy trì hơn.


1
Một điểm quan trọng: Casting CostIn một lần thay vì hai lần khiến nó không thể đọc được, bởi vì người đọc không biết liệu đây có phải là một lỗi tinh vi với một bản sửa lỗi rõ ràng hay liệu điều này được thực hiện có chủ ý. Rõ ràng nếu tôi không thể nói chắc chắn người viết có nghĩa gì trong một câu, thì nó không thể đọc được. Cần có hai diễn viên hoặc một bình luận giải thích lý do tại sao lần đầu tiên sử dụng CostIn không yêu cầu hoặc không nên có diễn viên.
gnasher729

3

Brevity không phải là một đức tính ở tất cả. Dễ đọc là đức hạnh.

Brevity có thể là một công cụ để đạt được đức tính, hoặc, như trong ví dụ của bạn, có thể là một công cụ để đạt được điều gì đó hoàn toàn ngược lại. Bằng cách này hay cách khác, nó hầu như không có giá trị của riêng nó. Quy tắc rằng mã phải "càng ngắn càng tốt" có thể được thay thế bằng "càng tục tĩu càng tốt" - tất cả đều vô nghĩa và có khả năng gây hại nếu chúng không phục vụ mục đích lớn hơn.

Ngoài ra, mã bạn đã đăng thậm chí không tuân theo quy tắc ngắn gọn. Các hằng số đã được khai báo với M hậu tố, hầu hết các kinh khủng (decimal)phôi có thể tránh được, như trình biên dịch sẽ thúc đẩy còn lại intđể decimal. Tôi tin rằng người mà bạn mô tả chỉ đơn thuần là sử dụng sự ngắn gọn như một cái cớ. Nhiều khả năng không cố tình, nhưng vẫn còn.


2

Trong những năm kinh nghiệm của mình, tôi tin rằng sự ngắn gọn cuối cùng là thời gian - thời gian chi phối mọi thứ khác. Điều đó bao gồm cả thời gian thực hiện - một chương trình mất bao lâu để thực hiện một công việc - và thời gian bảo trì - mất bao lâu để thêm các tính năng hoặc sửa lỗi. (Việc bạn cân bằng hai yếu tố này như thế nào tùy thuộc vào tần suất mã được đề cập so với cải thiện - hãy nhớ rằng tối ưu hóa sớm vẫn là gốc rễ của mọi tội lỗi .) Lực hấp dẫn của mã là để cải thiện sự ngắn gọn của cả hai; mã ngắn hơn thường chạy nhanh hơn, và thường dễ hiểu hơn và do đó duy trì. Nếu nó không làm gì, thì đó là một mạng âm.

Trong trường hợp được hiển thị ở đây, tôi nghĩ rằng sự ngắn gọn của văn bản đã bị hiểu sai là sự ngắn gọn của số lượng dòng, với chi phí dễ đọc, có thể làm tăng thời gian bảo trì. (Cũng có thể mất nhiều thời gian hơn để thực hiện, tùy thuộc vào cách thực hiện quá trình truyền, nhưng trừ khi dòng trên được chạy hàng triệu lần, điều đó có thể không đáng lo ngại.) Trong trường hợp này, các dấu thập phân lặp đi lặp lại làm mất khả năng đọc, vì nó khó hơn xem tính toán quan trọng nhất là gì Tôi đã có thể viết như sau:

decimal dIn = (decimal)CostIn;
decimal dOut = (decimal)CostOut;
return dIn > 0 && CostOut > 0 ? ((dOut - dIn) / dOut) * 100 : 0;

(Chỉnh sửa: đây là mã giống như câu trả lời khác, vì vậy bạn đi.)

Tôi là một fan hâm mộ của nhà điều hành ternary ? :, vì vậy tôi sẽ để nó ở đó.


5
Ternaries rất khó đọc, đặc biệt nếu có bất kỳ biểu thức nào vượt quá một giá trị hoặc biến trong các giá trị trả về.
Almo

Tôi tự hỏi nếu đó là những gì thúc đẩy các phiếu bầu tiêu cực. Ngoại trừ những gì tôi viết là đồng ý nhiều với Mason Wheeler, hiện ở mức 10 phiếu. Anh cũng rời khỏi chim nhạn. Tôi không biết tại sao rất nhiều người có vấn đề với ? :- tôi nghĩ ví dụ trên đủ nhỏ gọn, đặc biệt. so với một if-then-other.
Paul Brinkley

1
Thực sự không chắc chắn. Tôi đã không đánh giá thấp bạn. Tôi không thích chim nhạn vì nó không rõ những gì ở hai bên :. if-elseđọc như tiếng Anh: không thể bỏ lỡ ý nghĩa của nó.
Almo

FWIW Tôi nghi ngờ bạn đang bị downvote bởi vì đây là một câu trả lời rất giống với Mason Wheeler nhưng anh ấy đã nhận được câu trả lời đầu tiên.
Bob Tway

1
Cái chết cho người điều khiển chim nhạn !! (cũng vậy, cái chết đối với các tab, cũng như không gian và bất kỳ mô hình ngoặc và thụt nào ngoại trừ Allman (trên thực tế, The Donald (tm) đã tweet rằng đây sẽ là ba luật đầu tiên mà ông ban hành vào ngày 20)
Mawg

2

Giống như hầu hết tất cả các câu trả lời trên dễ đọc nên luôn luôn là mục tiêu chính của bạn. Tuy nhiên tôi cũng nghĩ định dạng có thể là một cách hiệu quả hơn để đạt được điều này qua việc tạo các biến và các dòng mới.

return ((decimal)CostIn > 0 && CostOut > 0) ?
       100 * ( (decimal)CostOut - (decimal)CostIn ) / (decimal)CostOut:
       0;

Tôi đồng ý mạnh mẽ với đối số phức tạp chu kỳ trong hầu hết các trường hợp, tuy nhiên chức năng của bạn có vẻ nhỏ và đủ đơn giản để giải quyết tốt hơn với trường hợp kiểm tra tốt. Vì tò mò tại sao cần phải đúc thành thập phân?


4
Lý do cho các diễn viên là Entity Framework. Các db cần lưu trữ chúng dưới dạng các loại nullable. Gấp đôi? không tương đương với Double in C # và cần được chọn.
Bob Tway

2
@MattThrower Ý bạn là decimalđúng không? double! = decimal, có một sự khác biệt lớn.
Pinkfloydx33

1
@ Pinkfloydx33 có! Gõ vào điện thoại chỉ với một nửa bộ não tham gia :)
Bob Tway

Tôi phải giải thích cho các sinh viên của mình rằng các kiểu dữ liệu SQL khác với các kiểu được sử dụng trong các ngôn ngữ lập trình. Tôi đã không thể giải thích cho họ tại sao mặc dù. "Tôi không biết!" "Tiểu endian!"

3
Tôi không tìm thấy cái này có thể đọc được.
Almo

1

Đối với tôi, có vẻ như một vấn đề lớn với khả năng đọc ở đây nằm ở việc thiếu định dạng hoàn toàn.

Tôi sẽ viết nó như thế này:

return (decimal)CostIn > 0 && CostOut > 0 
            ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 
            : 0;

Tùy thuộc vào loại CostInCostOutlà loại dấu phẩy động hay loại tích phân, một số phôi cũng có thể không cần thiết. Không giống như floatdouble, các giá trị tích phân được ngầm phát huy decimal.


Tôi rất tiếc khi thấy điều này bị hạ thấp không có lời giải thích, nhưng dường như tôi giống hệt với câu trả lời của ba lô trừ một số nhận xét của anh ấy, vì vậy tôi cho rằng nó hợp lý.
PJTraill

@PJTraill Tôi đã bỏ lỡ điều đó, nó thực sự gần như giống hệt nhau. Tuy nhiên, tôi thực sự thích có các nhà khai thác trên các dòng mới, đó là lý do tại sao tôi sẽ để phiên bản của mình đứng vững.
Felix Dombek

Tôi đồng ý về các nhà khai thác, như tôi đã nhận xét trong một nhận xét về câu trả lời khác - tôi đã không phát hiện ra rằng bạn đã làm điều đó như tôi muốn.
PJTraill

0

Mã có thể được viết vội vàng, nhưng mã trên trong thế giới của tôi nên được viết với tên biến tốt hơn nhiều.

Và nếu tôi đọc mã chính xác thì nó đang cố gắng thực hiện phép tính Grossmargin.

var totalSales = CostOut;
var totalCost = CostIn;
var profit = (decimal)(CostOut - CostIn);
var grossMargin = 0m; //profit expressed as percentage of totalSales

if(profit > 0)
{
    grossMargin = profit/totalSales*100
}

3
Bạn mất số chia cho số không trả về số không.
danny117

1
và đó là lý do tại sao thật khó để cấu trúc lại mã của người khác được tối đa hóa cho sự ngắn gọn và tại sao nên có thêm nhận xét để giải thích lý do tại sao / cách mọi thứ hoạt động
Rudolf Olah

0

Tôi giả sử CostIn * CostOut là số nguyên
Đây là cách tôi sẽ viết nó
M (Tiền) là số thập phân

return CostIn > 0 && CostOut > 0 ? 100M * (CostOut - CostIn) / CostOut : 0M;

1
hy vọng cả hai không suy nghĩ tiêu cực: p
Walfrat

2
Là thần thánh bằng không vẫn còn đó?
danny117

@ danny117 Khi brevity đưa ra câu trả lời sai thì nó đã đi xa.
paparazzo

Đừng muốn cập nhật câu hỏi và làm cho nó hoạt động. 100M và 0M buộc số thập phân. Tôi nghĩ (CostOut - CostIn) sẽ được thực hiện dưới dạng toán số nguyên và sau đó sự khác biệt được chuyển thành số thập phân.
paparazzo

0

Mã được viết để được mọi người hiểu; sự ngắn gọn trong trường hợp này không mua nhiều và làm tăng gánh nặng cho người bảo trì. Đối với sự ngắn gọn này, bạn tuyệt đối nên mở rộng điều đó bằng cách làm cho mã tự ghi lại nhiều hơn (tên biến tốt hơn) hoặc thêm nhiều bình luận giải thích lý do tại sao nó hoạt động theo cách này.

Khi bạn viết mã để giải quyết vấn đề hôm nay, mã đó có thể là vấn đề vào ngày mai khi yêu cầu thay đổi. Bảo trì luôn phải được tính đến và cải thiện tính dễ hiểu của mã là điều cần thiết.


1
Đây là nơi thực hành và nguyên tắc Kỹ thuật phần mềm phát huy tác dụng. Yêu cầu phi chức năng
hanzolo

0

Brevity không còn là một đức tính khi

  • Có Bộ phận mà không có kiểm tra trước cho số không.
  • Không có kiểm tra cho null.
  • Không có dọn dẹp.
  • TRY CATCH so với ném lên chuỗi thức ăn nơi có thể xử lý lỗi.
  • Giả định được thực hiện về thứ tự hoàn thành các nhiệm vụ không đồng bộ
  • Nhiệm vụ sử dụng độ trễ thay vì lên lịch lại trong tương lai
  • Không cần IO được sử dụng
  • Không sử dụng cập nhật lạc quan

Khi không có câu trả lời đủ dài.

1
Ok, điều này nên là một nhận xét, không phải là một câu trả lời. Nhưng anh ta là một chàng trai mới, nên ít nhất là giải thích; đừng chỉ downvote và chạy đi! Chào mừng, Daniel. Tôi đã hủy một downvote, nhưng lần sau hãy bình luận :-)
Mawg

2
Ok tôi đã mở rộng câu trả lời để bao gồm một số điều phức tạp hơn mà tôi đã học được một cách khó khăn và cách dễ dàng viết mã ngắn gọn.
danny117

Cảm ơn sự chào đón @Mawg Tôi muốn chỉ ra kiểm tra null là điều tôi gặp phải vấn đề gây ra nhiều nhất trong mã ngắn gọn.
danny117

Tôi chỉ chỉnh sửa qua Android và nó không yêu cầu mô tả về chỉnh sửa. Tôi đã thêm cập nhật lạc quan (phát hiện đã thay đổi và cảnh báo)
danny117

0

Nếu điều này đã vượt qua các thử nghiệm đơn vị xác nhận, thì nó sẽ ổn, nếu một thông số mới được thêm vào, một thử nghiệm mới hoặc một triển khai nâng cao được yêu cầu và nó được yêu cầu "gỡ rối" độ căng của mã, đó là khi vấn đề sẽ phát sinh.

Rõ ràng là một lỗi trong mã cho thấy rằng có một vấn đề khác với Q / A là một sự giám sát, vì vậy thực tế là có một lỗi không bị bắt là nguyên nhân gây lo ngại.

Khi xử lý các yêu cầu phi chức năng như "khả năng đọc" của mã, nó cần được xác định bởi người quản lý phát triển và được quản lý bởi nhà phát triển chính và được các nhà phát triển tôn trọng để đảm bảo triển khai đúng.

Cố gắng đảm bảo triển khai mã được chuẩn hóa (các tiêu chuẩn và quy ước) để đảm bảo "khả năng đọc" và dễ "bảo trì". Nhưng nếu các thuộc tính chất lượng này không được xác định và thi hành, thì bạn sẽ kết thúc bằng mã như ví dụ trên.

Nếu bạn không muốn xem loại mã này, thì hãy cố gắng để nhóm đồng ý về các tiêu chuẩn và quy ước thực hiện và viết nó xuống và thực hiện đánh giá mã ngẫu nhiên hoặc kiểm tra tại chỗ để xác thực quy ước đang được tôn trọng.

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.