Mã đẹp trong C ++ là gì và tại sao hầu hết các lập trình viên quan tâm đến vậy? [đóng cửa]


8

Vì hầu hết các dự án sử dụng API C ++, chúng xử lý các ràng buộc của API và các ràng buộc của chính dự án.

Tôi là người mới bắt đầu lập trình, tôi hoàn toàn không thích sử dụng OOP vì không ai giải thích rõ ràng cho tôi TẠI SAO Điều đó rất quan trọng để hạn chế phạm vi riêng tư của bạn để ngăn chặn các lập trình viên khác phá vỡ tính nhất quán của tổ chức dữ liệu.

Tôi vẫn có thể ổn với OOP, vì nó vẫn cho phép tạo ra một số điều tuyệt vời như Qt và Ogre3D, nhưng đó chỉ là các API, không phải ứng dụng và các mã đó cần phải hoàn hảo để không ai có thể chỉ trích công việc.

Tôi không hiểu tại sao hầu hết các lập trình viên, vì họ tạo ra các ứng dụng chứ không phải API, muốn tạo mã hoàn hảo như họ thiết kế một số đoạn mã thiên tài và lãng phí thời gian cho việc này.


19
Hãy cho nó một vài năm để quay lại mã cũ không hoàn hảo của bạn và thử thêm các tính năng cho nó, sửa các lỗi trong đó, v.v. thời gian xung quanh
R0MANARMY

Xem (câu hỏi này) [ lập trình viên.stackexchange.com / q / 65216/8823] . Không phải vì bạn không phải là lập trình viên, mà bởi vì có một số mô tả hay về lý do tại sao mã đẹp lại tốt
Austin Hyde

2
Đây có phải là câu hỏi về mã đẹp, OOP hoặc phạm vi riêng tư? Tôi thực sự không thể nói.
Sean McMillan

1
Wow ... không biết bắt đầu từ đâu. Hy vọng tôi không bao giờ phải xem hoặc làm việc với mã của bạn ...
Rig

1
Mã tốt và API tốt có rất nhiều điểm chung. Mã OOP tốt phải có giao diện trông giống hệt API được thiết kế tốt.
rwong

Câu trả lời:


12

Bạn đã bao giờ nghe câu nói "Không có ai là một hòn đảo" chưa?

Đối với hầu hết các lập trình viên điều này là đúng. Hầu như không ai viết mã "chỉ là một ứng dụng". Trên nhiều ứng dụng không tầm thường, một lập trình viên viết UI cần được nhà thiết kế dễ dàng sửa đổi. Nó cũng phải cho phép ràng buộc dữ liệu rõ ràng với logic nghiệp vụ (Trình điều khiển, ViewModel hoặc bất cứ điều gì bạn muốn gọi nó). Một lập trình viên khác viết rằng bộ điều khiển, thường có thể cực kỳ phức tạp, nhưng cần phải đủ đơn giản để có thể dễ dàng sử dụng bởi lập trình viên front end. Bộ mã hóa logic nghiệp vụ đó đang tiêu thụ mã từ bất kỳ ai đã viết lớp dữ liệu (Mô hình, Kho lưu trữ, v.v.). Bạn không phải sử dụng OOP, tuy nhiên, điều mà OOP khá giỏi là cho phép bạn đóng gói logic đằng sau một giao diện để những người khác làm việc với bạn có thể sử dụng mã của bạn mà không phá vỡ nó (giả sử bạn đã kiểm tra giao diện đó!). Trừu tượng không phải là viên đạn bạc,

Vì vậy, bây giờ bạn có thể nói "Nghiêm túc, tôi là một ngoại lệ và không ai sẽ thấy mã của tôi hoặc làm việc với nó cả". Đủ công bằng, nhưng khi bạn cần sửa một lỗi trong ứng dụng đó vài tháng kể từ bây giờ hoặc muốn thêm một vài tính năng, có thể bạn sẽ thấy rằng người đã viết mã đó sau đó và người đang sửa đổi nó bây giờ là Hai người hoàn toàn khác nhau. Chúng tôi thường cho rằng chúng tôi sẽ nhớ mọi thứ, đó là cốt lõi của lý do tại sao chúng tôi viết mã cẩu thả, nhưng sự thật là bản thân bạn sáu tháng kể từ bây giờ sẽ không nhớ các bản hack bạn đưa vào ứng dụng của bạn bây giờ. Con người tương lai của bạn sẽ có đủ để đối phó, vậy tại sao không cho anh ấy / cô ấy nghỉ ngơi?


43

Bất kỳ kẻ ngốc nào cũng có thể viết mã mà máy tính có thể hiểu. lập trình viên giỏi viết mã mà con người có thể hiểu được. ~ Martin Fowler

Điều đó, tóm lại, là lý do tại sao bạn muốn quan tâm đến mã đẹp.

Bạn không viết mã cho máy tính. Máy tính chỉ hiểu mã nhị phân (được tạo từ mã nguồn của bạn bằng cách biên dịch và phiên dịch). Nó không quan tâm đến vẻ đẹp hoặc sự rõ ràng hoặc thậm chí liệu mã của bạn có làm những gì nó phải làm hay không.

Bạn viết mã cho các lập trình viên đồng bào của bạn. Và họ làm tương tự cho bạn. Nếu bạn không thể hiểu một đoạn mã được viết bởi người khác, thì bạn nghĩ cơ hội của bạn là gì trong việc tìm và sửa lỗi hoặc thêm chức năng mới?


1
Tôi sẽ nói thêm rằng việc viết mã mật mã trong C ++ đặc biệt dễ dàng và đây là lý do tại sao điều này thậm chí còn quan trọng hơn trong ngôn ngữ này!
deadalnix

1
Vâng, tôi không thực sự đồng ý với trích dẫn này, mã có thể tái sử dụng là mã tốt, đúng, nhưng ngôn ngữ được tạo ra để lập trình viên có thể làm việc nhanh hơn, không nhất thiết phải được các lập trình viên khác đọc. Thật khó để đọc mã, vì vậy, hoặc đưa ra nhận xét hoặc thay đổi thiết kế để dễ hiểu hơn đối với con người, vâng, nhưng thiết kế tốt không phải lúc nào cũng đi kèm với "dễ hiểu". Một chương trình có thể thực thi cả các nhiệm vụ đơn giản và phức tạp và ngôn ngữ lập trình có thể giới hạn mức độ bạn có thể thiết kế các ứng dụng tinh vi. Ngôn ngữ lập trình làm cho mọi thứ dễ dàng hơn, không fancier.
jokoon

3

Những gì người khác đã nói như bạn không bao giờ biết nếu bạn có thể cần mã của mình một lần nữa trong tương lai là điều tất nhiên.

Nhưng đối với tôi có một điểm chính, tại sao tôi luôn cố gắng viết mã đẹp:

Đó là đào tạo để trở nên tốt hơn.

Nếu tôi học được điều gì đó mới về ngôn ngữ tôi sử dụng hoặc về một số khái niệm lập trình chung, tôi ngay lập tức cố gắng sử dụng ngôn ngữ đó, cố gắng biến nó thành một phần của quy trình làm việc hàng ngày và chuỗi công cụ tinh thần của tôi.

Nếu bạn chỉ đọc về một cái gì đó như OOP, bạn sẽ quên hầu hết trong số đó trong vài tuần. Và bạn sẽ không bao giờ được đào tạo cách áp dụng đúng cách cho các vấn đề lớn miễn là bạn không tự dạy mình bằng cách áp dụng nó cho các vấn đề nhỏ.

Thí dụ:

Tại sao điều quan trọng là hạn chế bản thân với phạm vi riêng tư?

Trong các dự án nhỏ thì không. Một số ngôn ngữ (ví dụ như Ruby) thậm chí không khuyến khích loại đóng gói này ở một mức độ nào đó. Nhưng có những công dụng cho nó. Nhiều.

Và sử dụng nó đi kèm với một số vấn đề nhất định và nhiều chi tiết bạn phải tìm hiểu. Sử dụng nó trong các dự án nhỏ sẽ dạy bạn điều này. Bạn sẽ thấy một số thông báo lỗi từ trình biên dịch mới đối với bạn và trong một dự án nhỏ, bạn sẽ có thể tìm thấy nguồn của vấn đề dễ dàng hơn.

Bạn tìm hiểu về không gian tên trong C ++. Không có nhiều nhu cầu cho họ trong các dự án nhỏ. Tương tự như vậy đối với cấu trúc thể loại của các tệp tiêu đề và bao gồm. Bạn có thể tìm hiểu tất cả những điều này sớm trong việc bảo vệ một cơ sở mã nhỏ.



1
  1. Những gì R0MANARMY đã nói trong bình luận của mình. Mã sạch & "đẹp" giúp bạn dễ đọc, hiểu, duy trì, thay đổi và sửa chữa hơn trong tương lai, không chỉ cho bản thân mà còn cho những người khác đến sau bạn.

  2. Một số người, khi họ làm một cái gì đó, cố gắng làm cho nó tốt nhất có thể, theo cách tốt nhất có thể, vì vậy nó là "hoàn hảo", hoặc trong trường hợp này là "đẹp". Tôi đã thấy rằng có một sự chồng chéo lớn giữa nhóm người và nhà phát triển này (bao gồm cả bản thân tôi!).

Mặc dù vậy, hãy ghi nhớ rằng "đẹp", "sạch sẽ" hoặc "thanh lịch" là những thuật ngữ mang tính chủ quan cao có nghĩa là những điều khác nhau đối với những người khác nhau. Từ những gì tôi đã thấy, mã được coi là đẹp, sạch sẽ và / hoặc thanh lịch,

  • Dễ đọc và dễ hiểu
  • Không có, hoặc ít, mã không cần thiết nằm xung quanh
  • Dễ dàng mở rộng và / hoặc mô-đun
  • Tài liệu tốt
  • Theo bất kỳ tiêu chuẩn nào cho các ngôn ngữ / công nghệ liên quan
  • Và không làm bất cứ điều gì bất ngờ (ví dụ: tác dụng phụ trong phương pháp truy cập)

1

Tôi đồng ý về điều duy trì. Chỉ cần cố gắng tự thực hiện một dự án tương đối lớn và bạn sẽ thấy tất cả những mớ hỗn độn liên quan đến việc sửa lỗi, thêm các tính năng mới, v.v. Nhưng để nói về vẻ đẹp:

Mã đẹp là chất lượng sản phẩm mong muốn vì (ít nhất, lập trình C ++) là một ART.


1
Mặc dù với sự ra đời của lambdas giờ đây không liên quan đến cá mập ít hơn trong formaldahyde
Martin Beckett

1

[...] Không ai có thể giải thích rõ ràng cho tôi TẠI SAO Điều đó rất quan trọng để hạn chế bản thân bạn trong phạm vi riêng tư để ngăn chặn các lập trình viên khác phá vỡ tính nhất quán của tổ chức dữ liệu.

Trong một nhóm đủ nhỏ với một cơ sở mã đủ nhỏ, thực sự phối hợp tốt với các tiêu chuẩn tốt (có thể chỉ là một người), bạn thường có thể tìm thấy phần mềm đáng tin cậy để mọi dữ liệu mở ra cho mọi người chạm vào với tất cả các trường dữ liệu của một structmở rộng tiếp xúc và với structđịnh nghĩa rộng mở cho bất cứ ai bao gồm tiêu đề đó để truy cập. Luật Murphy không phải lúc nào cũng áp dụng trong những trường hợp đó.

Nhưng tôi đã làm việc trong kịch bản ngược lại của một cơ sở mã khổng lồ với hàng triệu LỘC có niên đại từ thập niên 80 với một nhóm lớn các nhà phát triển từ khắp nơi trên thế giới, nơi chúng tôi chỉ gặp mặt nhau vài tháng, đôi khi được phối hợp một cách lỏng lẻo hầu như không nói cùng một ngôn ngữ, không có tiêu chuẩn mã hóa nào ngoại trừ SDK mà mọi người thường không tuân theo, dù sao cũng không kiểm tra đơn vị / tích hợp, sử dụng SVN mà không phân nhánh và đôi khi mất 6 tuần mà không kiểm tra mã, chỉ đánh bom chúng tôi với lỗi và Mãi đến lúc đó tôi mới thực sự hiểu giá trị của việc che giấu thông tin và duy trì bất biến .

Tôi đã xử lý các lỗi mà tôi thậm chí không thể tái tạo vấn đề một cách nhất quán trên máy của mình và đôi khi không ai trong chúng tôi có thể giữa cả nhóm. Và cuối cùng khi tôi may mắn có thể tái tạo vấn đề do người dùng báo cáo hoặc một cái gì đó tương tự như nó sau tất cả các loại thử nghiệm và lỗi (và bản dùng thử và lỗi thường mất hàng giờ vì phần mềm của chúng tôi không hiệu quả kết hợp với việc chạy nó trong quá trình gỡ lỗi đối với sản phẩm cuối của người dùng dữ liệu thường mất hơn 15 phút chỉ để tải dữ liệu), tôi sẽ theo dõi nó thành một dạng giống như structkiểu chuỗi có lentập hợp thành số âm, như độ dài chuỗi -921141282.

Điều đó không bao giờ nên xảy ra, nhưng ai đã làm điều đó? Vì vậy, tôi đã phải thiết lập các điểm dừng bộ nhớ và tìm hiểu, và khi cuối cùng tôi đã làm, nó giống như một sự tương tác xếp tầng của các biến chưa được khởi tạo được sử dụng một cách hợp lý, cuối cùng được thêm vào lentrường chuỗi được đặt thành số rác âm và mã đó không đã được sửa đổi trong năm. Nó bay theo radar.

Và tất cả thời gian đó sau khi gặp phải nhiều lỗi như thế này, tôi tự nghĩ, phần mềm của chúng ta sẽ đáng tin cậy hơn bao nhiêu nếu nó chỉ được sử dụng getterssetters? Getters và setters thường chỉ ra các loại thiết kế giao diện tồi tệ nhất có thể, nhưng một setter ít nhất có thể gây ra lỗi xác nhận nếu ai đó cố gắng đặt độ dài của chuỗi thành giá trị âm. Chúng ta có thể đã bắt được năm lỗi đótrước đó vào thời điểm chính xác nó được giới thiệu trong vài giây, không phải là đỉnh điểm của nhiều giờ nỗ lực điều tra. Và đó chỉ là suy nghĩ ích kỷ như một nhà phát triển; nó không bao gồm tất cả các giờ đau buồn mà nó có thể đã cứu cả người dùng và nhóm QA. Bạn biết rằng hệ thống của bạn đang ở một nơi khá tồi tệ khi bạn mơ về việc nó có thể tốt hơn bao nhiêu nếu nó sử dụng setters và getters khi đối mặt với 35 lỗi cuối cùng mà bạn đã dành cả đêm để sửa chữa.

Chúng tôi thậm chí đã có những trường hợp structsđược ghi lại theo cách nói rằng không ai khác nên truy cập vào các trường dữ liệu đó, chỉ để tìm các vị trí trong hệ thống truy cập vào các trường dữ liệu đó.

Vì vậy, đây là những điều bạn chỉ có thể thực sự đánh giá cao nhất bằng cách đối mặt với tình huống xấu nhất đó, nhưng bạn thường sẽ trừ khi bạn đủ may mắn để dành phần còn lại của cuộc đời mình để làm việc với các nhóm nhỏ hơn với các nhóm phối hợp tốt và tiêu chuẩn mã hóa mạnh mẽ.

Mã đẹp trong C ++ [...] là gì?

Đó là một trong những khó khăn. Tôi vẫn đang cố gắng để tìm ra điều đó. Hầu hết các mã tôi cho là đẹp mà tôi đã viết trong nhiều năm qua, hoặc ít nhất là đáng tin cậy và tương đối vượt thời gian và ổn định (không cần / muốn thay đổi) đã được viết bằng C và gần đây là Lua. Tôi vẫn đấu tranh để viết mã C ++ dường như vượt qua thử thách của thời gian đến mức tôi không phản ánh lại nó vài năm sau đó và ít nhất tôi ước mình có thể thay đổi nó. Tôi cảm thấy như mọi thứ trở nên dễ dàng hơn kể từ C ++ 11, nhưng tôi cần vài năm để tìm hiểu xem mã của tôi có thể tồn tại tốt như thế nào mà không cần thay đổi để chắc chắn. Đối với tôi, "vẻ đẹp" cuối cùng là "sự ổn định", vì trong mã không cần và thậm chí không cám dỗ bất kỳ thay đổi nào nữa nhưng vẫn còn phù hợp và hữu ích trong nhiều năm tới, vì điều đó '


0

Chà, xác định giao diện sạch và hữu ích ("đẹp" là một vòng loại kém) là tất cả về việc đảm bảo rằng:

  1. Người dùng hiểu được nỗi đau tối thiểu về cách sử dụng đối tượng của bạn (hoặc hệ thống các đối tượng) chỉ bằng cách đọc giao diện của nó.
  2. Người dùng sẽ gặp khó khăn khi sử dụng đối tượng / hệ thống sai cách - giao diện khiến bạn khó có thể làm gì đó sai hoặc báo hiệu sự cố sớm.
  3. Giao diện mô tả một sự trừu tượng hữu ích.

Các điểm 1. và 2. yêu cầu bạn phải suy nghĩ rất nhiều về hợp đồng bạn đang thực hiện với người dùng của mình. Hợp đồng đó, hoặc giao thức, là cách để giao tiếp với người dùng về cách anh ta có thể sử dụng hệ thống của bạn. Ví dụ, các hàm thành viên chỉ đọc (các hàm thành viên const) cho biết rất nhiều về các tình huống mà bạn có thể gọi hàm đó. Theo cùng một cách, các thuộc tính của từng chức năng sẽ khiến người dùng thu thập và cung cấp các thông tin tối thiểu cần thiết để hệ thống hoạt động.

Tất cả các điểm cùng nhau đề xuất rằng giao diện của bạn chỉ nên hiển thị các dịch vụ hữu ích cho người dùng. Đầu tiên để hạn chế việc sử dụng hệ thống của người dùng chỉ với những gì mà sytem được tạo ra. Thứ hai, bằng cách tránh anh ta để thao túng trạng thái nội bộ một cách sai lầm. Vì vậy, cách dễ nhất trong C ++ để đạt được điều này là đặt tất cả các thành viên riêng tư và nêu rõ các dịch vụ mà hệ thống của bạn cung cấp, sử dụng các hàm thành viên hoặc toàn cầu (trong không gian tên). Một cách khác là sử dụng thành ngữ PImpl.

Thứ ba, và quan trọng nhất: giao diện của bạn sẽ cung cấp một sự trừu tượng hữu ích, có nghĩa là người dùng không cần phải hiểu việc thực hiện. Khi tôi lái xe hơi hoặc máy giặt, tôi không muốn biết nó được chế tạo bên trong như thế nào (ngay cả khi tôi là người đam mê công nghệ ...). Tôi chỉ cần sử dụng nó và không phải bận tâm về những gì bên trong.

Nó khó.

Bất kỳ định nghĩa giao thức nào, như thiết kế ngôn ngữ lập trình hoặc thiết kế một lớp không rõ ràng như bạn có thể nghĩ trước tiên. Rất nhiều kinh nghiệm được yêu cầu để bảo vệ các mạng con của các giao diện mong muốn.

Tất cả những điều đó không được tiết lộ khi bạn xác định các cấu trúc hoặc các lớp đại diện cho các khái niệm mức rất thấp. Bạn càng nhận được cao từ phần cứng, hầu hết bạn cần phải có giao diện sạch sẽ, rõ ràng và hữu ích.

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.