Ruby: Phần xấu [đã đóng]


20

Gần đây tôi đã đọc cuốn sách "Javascript: Bộ phận tốt" của Crockford và một trong những tiền đề cơ bản là ngôn ngữ lập trình có thể có các bộ tính năng xấu mà các lập trình viên nên tránh.

Tôi là một người theo chủ nghĩa Ruby và trong khi tôi yêu ngôn ngữ thì luôn có giá trị trong việc có được viễn cảnh. Vậy, bạn thấy tính năng nào tệ nhất (ví dụ: phương thức, lớp học, thực tiễn) trong Ruby? Ý định của tôi ở đây không phải là bắt đầu một cuộc tranh luận về giá trị của ngôn ngữ hay tốc độ của nó, v.v. Thay vào đó, tôi thích thảo luận về những tính năng mà bạn cho là nguy hiểm / rắc rối / đau đớn khi sử dụng, dựa trên kinh nghiệm trong quá khứ.


1
Tôi chưa bao giờ là một người hâm mộ của việc phải sử dụng từ "kết thúc", và sau đó hỗn hợp của từ đó với "{" và "}" thậm chí còn khó chịu hơn. Nó khiến tôi đánh giá cao cú pháp kiểu Python hoặc thẳng lên {&} 's. Mặc dù người ta có thể tranh luận qua lại về vấn đề này, và cuối cùng nó có liên quan nhiều đến sở thích cá nhân. Tôi nghe ai đó nói rằng Ruby lấy những phần xấu nhất của Python và Perl và đặt chúng lại với nhau. Mặc dù vậy, tôi rất thích học Ruby.

Tôi thực sự rất thích câu hỏi này và sẽ mong chờ câu trả lời, nhưng vẫn bỏ phiếu để đóng nó. Tôi không nghĩ rằng nó phù hợp với Stack Overflow (do có thể quá chủ quan / tranh luận, kết thúc mở, v.v.).
stakx

Tôi nghĩ rằng nó đáng để thảo luận vì nó có thể làm sáng tỏ các thực hành nguy hiểm để tránh. Tôi thấy quan điểm của bạn mặc dù và chỉnh sửa câu hỏi để hẹp hơn.

9
Tôi không thấy câu hỏi này đủ khác biệt như thế nào, ví dụ những điều bạn muốn cải thiện trong ngôn ngữ Ruby là gì? , Ruby Gotchas mà một người mới nên được cảnh báo là gì? , Những vấn đề trong thế giới thực với Ruby là gì? hoặc bất kỳ câu hỏi đáng kinh ngạc nào khác về các điểm đau của Ruby. Thêm vào đó, ngay cả khi câu hỏi này được phát triển để phân biệt chính nó với những câu hỏi khác, nó sẽ thuộc về Lập trình viên . Không phải là StackOverflow.
Jörg W Mittag

2
Tôi cần phải kiểm tra mắt - Tôi nghĩ tiêu đề của câu hỏi này là "Ruby: The Brad Pitts".
oosterwal

Câu trả lời:


8

Bạn nên xem Python vs Ruby: A Battle to The Death của Gary Bernhardt. Ông đưa ra trích dẫn:

Chính những điều tôi thấy xấu xí ở Ruby là những gì làm cho phần mềm Ruby tuyệt vời như RSpec trở nên khả thi và Python không bao giờ có thể có được (với cách triển khai hiện tại).

Trong khi anh ấy nói rất nhiều về Python nói riêng, anh ấy đã chạm vào rất nhiều thứ kỳ lạ ở Ruby. Một trong những chủ đề bao trùm lớn là vá khỉ .

Các đối tượng Ruby (không giống như các đối tượng trong một số ngôn ngữ hướng đối tượng khác) có thể được sửa đổi riêng lẻ. Bạn luôn có thể thêm các phương thức trên cơ sở từng đối tượng. Trong Ruby, hành vi hoặc khả năng của một đối tượng có thể đi chệch khỏi những thứ được cung cấp bởi lớp của nó.

Mặc dù điều này cung cấp rất nhiều tính linh hoạt và tăng sức mạnh cho một số loại đá quý phổ biến và phức tạp nhất của Ruby, nó có thể cắn vào mông bạn nếu bạn đang cố gắng gỡ lỗi một vấn đề mà không nhận ra rằng một số thư viện ở đâu đó đã sửa đổi một phương pháp cốt lõi.


Javascript cho phép bạn đối xử với các đối tượng theo cách đó là tốt.
0112

8

Một số người chỉ nghĩ về ruby ​​về mặt ruby ​​trên đường ray và điều đó hơi khó chịu vì ngôn ngữ này tự nó khá tốt.


7

Tôi nghĩ rằng tính năng tồi tệ nhất là open classescho phép bạn thay đổi toàn cầu hành vi của tất cả các trường hợp hiện tại và tương lai của lớp đã thay đổi.

Phần có vấn đề của tính năng này là, những thay đổi (toàn cầu) xảy ra trong thời gian chạy khi trình thông dịch Ruby xuất hiện định nghĩa, có thể rất lâu sau khi bạn đã khởi tạo một vài đối tượng đột nhiên thay đổi hành vi của chúng.

Trong một cơ sở mã lớn, điều này có thể dẫn đến các lỗi rất, rất khó tìm thấy - đặc biệt là khi điều này được kết hợp bởi câu chuyện gỡ lỗi yếu của Ruby (ví dụ như câu chuyện gỡ lỗi CLR hoặc JVM) và sử dụng các tính năng khác (ví dụ eval) trong ngữ cảnh này có thể tạo ra khá khó để tìm vị trí xảy ra sự thay đổi toàn cầu này. tức là nếu bạn đã đạt đến điểm mà bạn nghi ngờ lớp 'đúng' gây rắc rối! Theo kinh nghiệm của tôi, bạn thường bắt đầu với một cuộc săn đuổi ngỗng hoang dã, vì các vấn đề bắt đầu nổi lên ở một đối tượng sử dụng thủ phạm thực sự.

Vì vậy, điều tốt nhất là, hoặc ngừng sử dụng các lớp mở ( #extendvà đặt các thay đổi trong một Modulelà IMHO an toàn hơn, dễ hiểu hơn và tốt hơn để kiểm tra) hoặc nếu không thể tránh được:

  • chỉ mở rộng các lớp với hành vi mới (tức là không ghi đè hành vi hiện có)
  • có một vị trí được xác định trong cây mã nguồn, nơi tất cả các phần mở rộng sử dụng các lớp mở phải được đặt
  • không sử dụng #evalvà bạn bè để tạo các lớp mở
  • đặt tất cả các tập quán của các lớp mở lên một biểu đồ lớn có thể nhìn thấy, nơi tất cả các nhà phát triển có thể nhìn thấy chúng - và làm rõ rằng mọi thay đổi trên chúng là 'quyết định kiến ​​trúc' ảnh hưởng đến toàn bộ cơ sở mã (mà chúng làm) và không phải là nơi để hack nhanh cho nhiệm vụ hiện tại của bạn

5

Lý do lớn nhất tôi không sử dụng Ruby: Nó chậm hơn mật đường vào tháng 1 ở Bắc Cực trong thời kỳ băng hà. Ngôn ngữ điểm chuẩn là một khoa học không chính xác, nhưng Ruby xuất hiện chậm hơn nhiều so với JavaScript và Python.


đó cũng là kinh nghiệm của tôi
Chuck Stephanski

2
ứng dụng bạn đã phát triển cho ruby ​​quá chậm là gì? Ý tôi là, tôi tin bạn khi bạn nói nó chậm, nhưng làm thế nào nó ngăn bạn đạt được mục tiêu?
David

1
Tôi nghĩ rằng Ruby thật tuyệt vời khi bạn muốn tạo ra một thứ giống như nguyên mẫu và muốn nó được thực hiện nhanh chóng, thứ gì đó không lớn và sẽ không bị khủng hoảng. Nếu bạn mong đợi được nhai nhiều chu kỳ CPU liên tục, bất kỳ lập trình viên giỏi nào cũng biết sử dụng một cái gì đó như C hoặc C ++.
Jeff Welling

1
@David: Tôi sẽ cân nhắc sử dụng Ruby cho mã xử lý chuỗi DNA đơn giản, nhưng tôi không vì Python lấp đầy một phân khúc tương tự, có các tính năng tương tự và nhanh hơn nhiều. Nếu tôi sẵn sàng xuống cấp thấp hơn, D thậm chí còn nhanh hơn và vẫn thuận tiện.
dsimcha

1
@Jeff: Đồng ý, nhưng C và C ++ là một nỗi đau để viết. Quan điểm của các ngôn ngữ cấp cao như Ruby là tránh đối phó với nỗi đau này càng nhiều càng tốt. Càng chậm, họ càng hoàn thành tốt mục tiêu này. Ruby chậm chạp ngay cả đối với một ngôn ngữ năng động cấp cao. Đó và NumPy / SciPy là lý do tại sao tôi sử dụng Python thay thế khi tôi cần một ngôn ngữ động cấp cao.
dsimcha

4

Nếu điều này có thể được mở rộng thành Ruby on Rails, thì:

  1. Thực tế là logic cơ sở dữ liệu cung cấp cho mỗi bảng một auto_incrementkhóa chính, bao gồm các bảng không cần chúng và không nên có chúng.

  2. Thực tế là các phím ghép không được hỗ trợ.

Đối với Ruby đơn giản, sự kìm kẹp của tôi sẽ giống như với bất kỳ ngôn ngữ nào đánh đổi sự an toàn cho tính biểu cảm; Thật dễ dàng để làm rất nhiều chỉ với một ít mã, nhưng thật dễ dàng để tạo ra một mớ hỗn độn lớn với bất kỳ số lượng mã nào.


Vui lòng xem các chỉnh sửa của tôi khi tôi thu hẹp phạm vi câu hỏi. Tôi sẽ bắt đầu một bản song song khác cho Rails nếu câu hỏi này với các chỉnh sửa được chấp thuận.

1
Xin lỗi, nhưng bạn đã nhầm, không phải mọi bảng trong ứng dụng Rails đều phải có auto_incrementid, đáng chú ý là các bảng tham gia cho các mối quan hệ has_and_belongs_to_many được đề xuất rõ ràng KHÔNG có cột id.
Brett Bender

@Brett - Là những bổ sung tương đối mới? Khi tôi chơi với nó hồi đầu năm 2008, nó chắc chắn không có những tính năng đó. Trong mọi trường hợp, thật tuyệt khi chúng có sẵn ngay bây giờ.

1
@aroth: Tôi không chắc chắn rằng mọi người khác sẽ coi "tương đối mới" có nghĩa là "trong vòng ba năm qua" :-)

Có một giải pháp thay thế cho ActiveRecord của Rails được gọi là DataMapper , không được coi là ActiveRecord.
Endy Tjahjono

3

Ruby chấp nhận siêu lập trình (phản xạ, hướng nội), lập trình đa mô hình và tính năng động ở mức độ không phổ biến. Thật dễ dàng để tự bắn vào chân mình bằng sức mạnh và sự linh hoạt.

Khó khăn? Ruby có khả năng cực kỳ dễ đọc hoặc không thể phá vỡ. Tôi đã thấy mã trông giống như trong tập lệnh Bash.

Thực tiễn xấu? Một số Rubyist coi trọng sự thông minh hơn trí tuệ. Họ viết và chia sẻ các thủ thuật thể hiện sự thông minh của họ, nhưng điều này tạo ra mã không thể đọc được và dễ vỡ.

Bên cạnh đó: Javascript là một thảm họa bởi thiết kế và cuốn sách "Những phần tốt" cố gắng lấy ra vẻ đẹp tiềm ẩn của nó. Perl, một ngôn ngữ phổ biến "Có nhiều cách để làm điều đó" (nghĩa là linh hoạt), có một cuốn sách tương tự trong "Perl, Thực tiễn tốt nhất". Lịch sử của Perl là một trong những thử nghiệm và kinh nghiệm khó thắng, "Thực tiễn tốt nhất" đại diện cho kiến ​​thức của nó. Perl 6 sẽ, tôi nghĩ thật công bằng khi nói, việc khởi động lại ngôn ngữ dựa trên kiến ​​thức đó và hơn thế nữa. Ruby có thể bị các vấn đề tương tự.

@James và cho các vòng lặp ... Khi bạn thực hiện một vòng lặp for trong ruby, nó sẽ gọi ".each". Do đó, "for" là đường cú pháp giúp mọi người thoải mái hơn với các vòng lặp kiểu C. Nhưng là một Rubyist, bạn sẽ sử dụng các trình vòng lặp như .map, .inject, .each_with_object, mọi lúc. Bạn sẽ không bao giờ phải viết một vòng lặp for với nội dung như "i = 0; i> 6; i ++" bằng ruby, và vì vậy cuối cùng bạn đã bỏ thói quen này. @andrew ... ruby ​​hùng hồn không chứng thực cho các vòng lặp.


-1

Đây là về các lập trình viên nhiều hơn ngôn ngữ, nhưng tại sao các lập trình viên Ruby ghét các vòng lặp quá nhiều?

Tôi nhận ra Ruby có:

someCollection.each do |item|
   ...
end

nhưng tôi chưa bao giờ thấy rằng được sử dụng trong các tình huống trong đó một vòng lặp for sẽ không thực hiện chính xác điều tương tự.

Tôi đã hỏi nhiều lần và không bao giờ nhận được câu trả lời hay cho câu hỏi này.

Nếu đó chỉ là một phong cách, tôi rất vui khi chấp nhận điều đó, nhưng tôi đã thấy các lập trình viên Ruby thực sự làm việc về điều này và tôi thực sự tò mò.


1
Ngay cả khi tôi đã nhận được câu trả lời "Đó là cách nhấn phím ít hơn", điều này rõ ràng sai ... :-)
James

2
Hai lý thuyết: 1) Sử dụng forcác vòng lặp là điều mà n00bs làm. Những người đang lập trình C trong Ruby. 2) Các khối được sử dụng rất nhiều trong Ruby, vì vậy sử dụng thứ gì đó không giống khối chỉ là nỗ lực tinh thần thêm.
Andrew Grimm

3
Trong khi tôi mới bắt đầu học Ruby, các khối là thứ mà tôi thực sự thích và bỏ lỡ khi tôi cố gắng sử dụng Python. Một vòng lặp for sẽ làm điều tương tự? Tất nhiên, với tôi, kiểu này chỉ phù hợp với sở thích của tôi hơn là vòng lặp for.
Jetti

2
@andrew Thành thật mà nói, câu trả lời đầu tiên của bạn chính xác là loại rác tôi đã trả lại khi tôi hỏi trước đó. Không có lý do thực sự, với một sự xúc phạm tinh tế trên đầu trang. @Wayne, @Jetti và @andrews Câu trả lời thứ 2: cảm ơn. Đủ công bằng rồi.
James

1
Nếu bạn có nghĩa là "nâng cao" cho các vòng lặp (còn gọi là <value> trong <biểu thức> làm ...) thì không có gì khác biệt ngoài việc #each đang được sử dụng và xuất hiện gần hơn với anh em họ thường sử dụng #inject, #collect, # từ chối, v.v ... Nếu bạn đang nói về các vòng lặp được lập chỉ mục kiểu 'C' (hay còn gọi là int i = 0; i <anything; ++ i) thì sự khác biệt là, a) lỗi "tắt bởi một" là không thể và b) rằng nó làm cho ý định của vòng lặp của bạn rõ ràng - #each có nghĩa là "cho mỗi phần tử tạo ra hiệu ứng phụ". Một vòng lặp for yêu cầu bạn đọc toàn bộ vòng lặp chỉ để có được 'ý chính' của mục đích của nó.
Alexander Battisti

-1

Nói chung, tôi nên tránh những thứ được thêm vào để tương thích ngược với các ngôn ngữ khác. Ví dụ, Perlism và for x in y.


Tôi vừa đăng câu trả lời về Lập trình viên Ruby và các vòng lặp, và nếu bạn có thể giải thích tôi sẽ biết ơn :-)
James
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.