Làm cách nào để ghi lại mã của tôi để xem xét thời gian tối thiểu? [đóng cửa]


22

Tôi muốn ghi lại mã của mình sao cho có nhu cầu tối thiểu để đọc và duyệt lại mã một tháng sau đó.

Tôi biết rằng có nhiều loại tài liệu khác nhau (trong mã nguồn và bên ngoài, sơ đồ trình tự, v.v.).

Tôi chỉ muốn biết đâu là cách hiệu quả để ghi lại mã của mình để khi vài tháng sau tôi muốn xem mã của mình, tôi dành ít thời gian hơn để đọc mã và hiểu dòng mã.


42
Phương pháp tốt nhất để dành ít thời gian đọc mã sau này là viết mã rõ ràngdễ hiểu hơn .
Mael


Các tài liệu phụ thuộc vào mục tiêu. Nếu bạn đang giải quyết cho các nhà phát triển, thì các bình luận trong mã khá hữu ích. Nếu bạn đang giải quyết cho các nhà phân tích, sơ đồ của tổng quan cũng hữu ích. Nếu bạn đang nhắm đến đối tượng am hiểu công nghệ, hãy làm hướng dẫn sử dụng.
Laiv

@Laiv Vâng theo quan điểm của một nhà phát triển mã của riêng tôi và có thể mã nhà phát triển khác.
Hamed_gibago

Điều lớn nhất là giữ cho mã nhỏ. Nếu mã cần thiết để triển khai một mục trong hệ thống theo dõi vấn đề của bạn lớn, thì nhóm của bạn có thể cần học cách phá vỡ thêm một số để số lượng mã được xem xét không quá nhiều.
Berin Loritsch

Câu trả lời:


16

Tôi phải thừa nhận rằng tôi không đồng ý với một số điều mà các câu trả lời khác đề nghị, vì vậy tôi sẽ ném hai xu của mình;

Bình luận

Tài liệu cực kỳ hữu ích cho những người lạ đọc mã của bạn. Thông thường nhiều thứ sẽ không đủ dài để được đọc và hiểu ngay lập tức, và sau đó bạn nên giải thích những gì bạn đang làm.

Chỉnh sửa : cuộc thảo luận trong phần bình luận đã chỉ ra điều gì đó đúng - bình luận quá mức thường được thực hiện khi viết mã xấu .

Nhận xét công việc của bạn nên chính xác và tối thiểu, nhưng, theo tôi, chắc chắn nên có mặt. Ít nhất là một nhận xét cho mỗi 15 dòng mã. Ví dụ: trên đầu các khối trên mã, hãy thêm một dòng về những gì bạn đang làm:

def login(username: str, password: str, create_session: bool = True):

    # Filter the user we need from the database
    hash = md5(password)
    users = db.table("users", db_entities.USER)
    results = [x for x in users.query(lambda c: c.get("username") == username and c.get("password_hash") == hash)]


    if len(results) == 0:
        return None, None
    else:
        # Create a login session record in the database.
        if create_session:
            sessions = db.table("sessions", db_entities.SESSION)
            ses = sessions.new()
            ses.set("username", username) \
                .set("expiery", 31536000 + time.time())
            sessions.update(ses)
            return results[0], ses
        else:
            return results[0], None

Nhận xét tối thiểu giải thích lý donhững gì bạn đang làm là rất hữu ích trong suốt mã. Tôi không đồng ý với câu trả lời rằng

Nếu tôi gặp phải mã chứa các bình luận, tôi sẽ chuẩn bị cho điều tồi tệ nhất: mã có khả năng là xấu và thành thật mà nói, các bình luận cũng có khả năng xấu.

Nhiều lần, duyên dáng, mã tốt được ghi lại. Đúng là các lập trình viên xấu nhìn thấy tài liệu của họ như "Được rồi, mã của tôi rất tệ, hãy thêm một vài câu để làm cho nó rõ ràng hơn".

Vâng, và trong khi điều này xảy ra khá nhiều, thì cũng đúng là các lập trình viên giỏi viết mã sạch cũng muốn đảm bảo rằng họ quay lại mã của họ và hiểu lý do tại sao họ muốn chức năng của họ hoạt động như vậy hoặc tại sao họ cần điều đó dòng có vẻ hơi dư thừa, v.v ...

Vâng, các bình luận giải thích những điều hiển nhiên, các bình luận không rõ ràng, các bình luận được đặt cùng nhau để đảm bảo rằng "mã này được ghi lại, yeah, sao cũng được", là mùi mã. Họ làm cho việc đọc mã khó khăn và khó chịu hơn. (Thêm một ví dụ dưới đây)

# Logging into Gmail when the module is imported
_client = login()
def get_client():
    global _client
    return _client

Ví dụ làm rõ: "Không shit, Sherlock. Có _client = login()đăng nhập vào dịch vụ thư không? OMG!"

Làm rõ hơn: login()phương thức không liên quan đến login()phương thức từ ví dụ trên.

Nhưng những bình luận không phù hợp với tiêu chuẩn, giải thích lý do tại sao chứ không phải như thế nào và trả lời đúng câu hỏi , rất hữu ích.

Nội dung bình luận

Một điều bạn nên KHÔNG (và nếu tôi có thể viết rằng lớn hơn, tôi sẽ) làm là viết bình luận của bạn trong cùng một dòng mã. Nó làm cho các bình luận rất cụ thể, mà hoàn toàn bỏ lỡ mục đích bình luận mã của bạn.

Ví dụ: bình luận nội tuyến xấu:

outer = MIMEText(details["message"]) # Constructing a new MIMEText object
outer["To"] = details["to"] # Setting message recipient
outer["From"] = "xAI No-Reply" # Setting message sender
outer["Subject"] = details["subject"] # Setting message subject
outer.preamble = "You will not see this in a MIME-aware mail reader.\n" # I don't know what I'm doing here, I copied this from SO.
msg = outer.as_string() # Getting the string of the message
_client = details["client"] # Assigning the client
_client.sendmail(SENDER, details["to"], msg) # Sending the mail

Sẽ dễ dàng hơn nhiều để đọc và hiểu mã này mà không có ý kiến, điều đó làm cho nó lộn xộn và không thể đọc được.

Thay vào đó, các bình luận bên trong mã của bạn nên được đặt phía trên các khối trên mã và chúng sẽ trả lời các câu hỏi quan trọng có thể phát sinh trong khi đọc khối mã.

# Constructing the email object with the values 
# we received from the parameter of send_mail(details)
outer = MIMEText(details["message"])
outer["To"] = details["to"]
outer["From"] = "xAI No-Reply"
outer["Subject"] = details["subject"]
outer.preamble = "You will not see this in a MIME-aware mail reader.\n"
msg = outer.as_string()

# Sending the mail using the global client (obtained using login())
_client = details["client"]
_client.sendmail(SENDER, details["to"], msg)

Rõ ràng hơn nhiều, phải không? Bây giờ bạn cũng biết rằng bạn phải sử dụng login()hàm và cung cấp các tham số cho send_mail()mọi thứ bạn đã sử dụng. Giúp một chút, nhưng một điều vẫn còn thiếu.

Tài liệu chức năng

Đã được thảo luận rộng rãi. Bạn nên luôn luôn cho độc giả của bạn biết chức năng của bạn là gì, tại sao và nó làm gì. Làm thế nào nó làm điều đó, điều này không thuộc về tài liệu, nhưng có thể là chú thích của chức năng.

Bạn nên mô tả rõ ràng những gì bạn mong đợi các tham số của mình và nếu bạn muốn chúng được lấy / tạo trong một phương thức cụ thể. Bạn nên khai báo chức năng của bạn sẽ trả về, công dụng của nó là gì, v.v.

Một lần nữa, đó là ý kiến ​​và phương pháp của tôi trong khi viết mã của tôi. Không chỉ những điều đó, mà đó chỉ là một số điều tôi không thể đồng ý với các câu trả lời khác. Ồ, và tất nhiên, không chỉ các bình luận đọc mã của bạn, mà chính mã của bạn. Viết mã sạch, dễ hiểu và có thể duy trì . Nghĩ về bản thân tương lai của bạn trong khi viết mã ;-)


5
Không đồng ý với một ví dụ cụ thể - thay vì viết nhiều bình luận trong một hàm lớn, bạn nên soạn nó từ nhiều hàm nhỏ hơn với các tên mô tả, sẽ đóng vai trò là các bình luận. Không có nguy cơ không đồng bộ với những gì mã thực sự đang làm.
dùng11153

6
Cuối cùng cũng tỉnh táo. Trích xuất mọi đoạn mã có thể sử dụng một nhận xét vào chức năng của chính nó là cách bạn kết thúc với hàng ngàn hàm trải rộng trên hàng trăm tệp.
dùng369450

2
Đó là ví dụ thứ hai thật đáng yêu.
Cuộc đua nhẹ nhàng với Monica

7
Các ý kiến ​​trong ví dụ thứ hai quá dài dòng. Một số trong số họ (ví dụ: "Chúng tôi có tìm thấy gì không?") Chỉ cần lặp lại những gì mã nói và sẽ được loại bỏ tốt hơn. Mặt khác, bạn có thể đạt được nhiều khả năng đọc hơn bằng cách tái cấu trúc, như tạo (stream.is_empty ()) điều kiện vòng lặp hoặc di chuyển kiểm tra accept_literals bên ngoài.
Frax

3
@cpburnz, "Tôi đã phải tìm hiểu quá nhiều dự án cũ và thư viện của bên thứ ba mà không có bất kỳ nhận xét mã nào để đánh giá cao các bình luận giải thích những gì đang xảy ra và tại sao". chính xác quan điểm của tôi tất cả cùng: ý kiến ​​là có để giải thích mã crap. Vì câu hỏi là "làm thế nào để tôi viết mã dễ đọc" nên rõ ràng câu trả lời này là sai vì nó tập trung vào việc viết bình luận để giải thích mã xấu, thay vì viết mã tốt ngay từ đầu.
David Arno

55

IMO tài liệu tốt nhất là tài liệu bạn không thực sự cần. Tôi cũng ghét viết tài liệu và ý kiến.

Với điều đó đang được nói:

  • Chọn tên dễ đọc và nói. Đừng sử dụng n, nhưng thay vào đó là numberOfItemsFoundví dụ.
  • Đừng ngại lưu trữ các phần của phép tính trong một biến không đổi thay vì đẩy mọi thứ vào một dòng.
  • Chuyển các tác vụ một phần từ các nhánh sang các hàm (nội tuyến) của riêng chúng, nếu bạn đang sử dụng lại chúng hoặc hàm cha trở nên dài và tẻ nhạt.
  • Hãy trau chuốt hơn và chỉ tối ưu hóa mã trên khả năng đọc khi thực sự cần thiết.

19
Đây là một số liệu tốt cho tài liệu (liên kết bắt buộc).
Neil

4
Điều này cũng nên có trong danh sách: giải thích bằng mã tại sao bạn đang làm những việc bạn đang làm.
t3chb0t


4
numberOfItemsFoundlà khá dài dòng mặc dù; quá dài dòng cũng là một vấn đề.
Matthieu M.

6
@MatthieuM., Hiếm khi "quá dài dòng" một vấn đề với tên trong mã. Quá ngắn gọn hoặc khó hiểu là một vấn đề rất phổ biến mặc dù.
David Arno

25

Hãy coi mã của bạn là tài liệu

Mã của bạn là tài liệu chính của bạn. Nó mô tả chính xác những gì ứng dụng kết quả, thư viện hoặc bất cứ điều gì, thực sự làm. Như vậy, bất kỳ nỗ lực nào nhằm tăng tốc độ hiểu biết về mã đó phải bắt đầu bằng chính mã đó.

Có rất nhiều điều được viết về cách viết mã có thể đọc được, nhưng một số điểm chính là:

  • không dựa vào các bình luận để giải thích mã xấu, làm cho mã tốt hơn và thoát khỏi các bình luận,
  • viết các hàm tập trung ngắn, các phương thức, các lớp, v.v.
  • sử dụng tên phù hợp với bối cảnh (ví dụ: ntốt cho vòng lặp, tên mô tả dài hơn là cần thiết cho các mục có phạm vi lớn hơn),
  • đối xử với các tên hàm như thể chúng là các bình luận, ví dụ: không sử dụng UpdtTblvới một bình luận giải thích nó cập nhật bảng với các quy tắc được cung cấp khi UpdateTableContentsWithSuppliedRulescó thể được sử dụng làm tên,
  • tránh sự biến đổi Mỗi khi bạn thay đổi nội dung của một biến, bạn sẽ tăng độ phức tạp của mã. Gán giá trị mới đó cho một biến mới (có tên hay) khi khả thi.
  • cuối cùng, và quan trọng nhất, tránh mã "thông minh". Mã thông minh thực sự duy nhất là mã dễ đọc. Nếu bạn viết một số đoạn mã phức tạp và thấy mình nghĩ "wow, tôi không thông minh ở đây à?", Câu trả lời gần như được đảm bảo là "không, bạn không".

Trở nên tốt hơn trong việc đọc mã

Đọc mã, bất kể nó đơn giản như thế nào, là một kỹ năng được học. Không ai tự nhiên giỏi đọc mã. Nó cần thực hành; rất nhiều thực hành. Vì vậy, ví dụ, đi đến Github hoặc bất cứ điều gì và đọc mã của các thư viện mà bạn sử dụng, thay vì chỉ sử dụng các thư viện đó. Tìm mã để đọc và đọc nó.

Nhận xét là một mùi mã

Chỉ sau đó chúng ta có được các loại tài liệu khác. Thứ nhất, như đã nêu trước đó, tránh bình luận. Nếu tôi gặp phải mã chứa các bình luận, tôi sẽ chuẩn bị cho điều tồi tệ nhất: mã có khả năng là xấu và thành thật mà nói, các bình luận cũng có khả năng xấu. Một người không thể giao tiếp tốt thông qua mã dường như không thể giao tiếp tốt hơn thông qua ngôn ngữ tự nhiên.

Coi chừng tài liệu API tự phát

Ngoài ra, hãy cẩn thận tài liệu API tự phát. Nếu tôi phải dùng đến việc đọc các tài liệu đó, thì đó là do mã của bạn rất khó đọc. Một lần nữa, làm cho mã đơn giản và tôi có thể đọc nó trực tiếp.

Các bài kiểm tra cũng là tài liệu

Các xét nghiệm là tài liệu quá. Vì vậy, đừng coi các bài kiểm tra đơn vị của bạn là một việc vặt. Đối xử với họ như một cách để giao tiếp với người khác (bản thân sáu tháng sau của bạn được đưa vào đây) như cách mã hoạt động và dự định sẽ được sử dụng.

Vẽ hình nếu nó giúp

Nếu bạn thích UML, thì bằng mọi cách, hãy tìm cho mình một công cụ tốt và tạo sơ đồ UML từ mã của bạn. Không bao giờ từng cố gắng sử dụng nó để tạo mã. Nó không tốt như một công cụ thiết kế và kết quả là bạn sẽ có mã khủng khiếp.

Có tài liệu xem "1000ft"

Cuối cùng, viết cho mình một tài liệu tổng quan. Ứng dụng này làm gì? Làm thế nào để nó làm điều đó? Nó kết nối với những hệ thống nào khác? Những thứ như vậy. Đừng cố gắng để mô tả cấu trúc mã ở đây mặc dù. Hãy để mã làm điều đó. Hãy để tài liệu này nhắc nhở bạn tại sao bạn viết mã ở vị trí đầu tiên.


14
Tôi đồng ý với tất cả quan điểm của bạn, ngoại trừ ý kiến ​​đó có vị trí của họ. Mặc dù tôi đồng ý rằng không có điểm nào trong các bình luận như thế nào add 1 to i, các bình luận sẽ giải thích tại sao mã lại làm những gì nó làm. Ví dụ: mã if (!something.Exists()) {...}có thể sử dụng một nhận xét như : // something exists only when (explanation of the broader scenario).
Jonathan

16
Tất cả chúng ta đều đã thấy những chia sẻ công bằng của chúng ta về // increment x x++;những bình luận không có ích gì, nhưng thật sai lầm khi ném em bé ra ngoài bằng nước tắm và tuyên bố rằng những bình luận luôn xấu. Ví dụ, ý kiến ​​của mẫu // this case should never happen because xyz throw exception "unreachable".
tức giận

7
Danh sách rất hay. Nhưng giống như @Jonathan. Tôi không đồng ý với ý kiến. Đôi khi bạn phải tính đến các lỗi trong khung của bên thứ ba. Mặc dù điều này có thể được tái cấu trúc thành chức năng của chính nó, nhưng vẫn tốt để lại một chút mô tả về lý do tại sao cách giải quyết (bugnumber hoặc bugname / mô tả lỗi) là bắt buộc.
magu_

16
@DavidArno Nhưng bạn không thể làm điều đó cho một bình luận giải thích lý do tại sao một cái gì đó không được thực hiện. Thích //XXX: Not using straight-forward method Foo here because .... Những bình luận như vậy có thể rất có giá trị, nhưng không thể truyền đạt bằng mã vì những lý do rõ ràng.
cmaster

7
Tôi thích nó thậm chí còn kịch tính hơn: mỗi bình luận là một thất bại để thể hiện bản thân tốt trong mã . Ví dụ: tôi có một nhận xét 4 dòng trong một phương thức, giải thích cách giải quyết cho lỗi của bên thứ 3. Tôi đã không thể hiện tốt điều đó trong mã, vì vậy nó là một bình luận . Tôi muốn nói rằng nó đã cải thiện khả năng đọc khó khăn, bởi vì tôi nghi ngờ bất kỳ ai cũng sẽ thích cuộn theo chiều ngang để đọc một tên phương thức rất dài và rất mô tả. "Nhận xét là một mùi mã" - vâng, nhưng chúng ta phải nhớ rằng không phải tất cả mọi thứ có mùi đều là sh * t.
R. Schmitz

5

Cung cấp thư xin việc

Trừ khi bạn ở trong một lĩnh vực rất kỹ thuật, hầu hết các câu hỏi xung quanh mã sẽ không phải là về 'làm thế nào' mà là về 'tại sao' hoặc 'cái gì'.

Như vậy, cách để giảm bớt mọi người khỏi phải tìm mã của bạn, là viết một mô tả ngắn về nó. Ưu điểm của việc này là bạn có thể biên dịch tổng quan về các mô tả khá dễ dàng, và điều này đáng tin cậy hơn nhiều. (Ngay cả với những người sẽ không / không được phép xem mã).

Ngay cả khi mọi người là kỹ thuật, thư xin việc nên cung cấp hướng dẫn về nơi họ nên tìm kiếm một cái gì đó.

Điểm cực kỳ đơn giản:

  1. Giới thiệu, tại sao mã này (cơ sở) tồn tại
  2. Các tập hợp con mã thực hiện chức năng gì
  3. Mã ở đâu (ví dụ tên tập lệnh)

Thí dụ

  1. Tập lệnh này loại bỏ StackOverflow và nâng cao câu trả lời của Dennis Jaheruddin
  2. a. Kịch bản này chịu trách nhiệm phân tích cú pháp html và phân tích xem đó có phải là người dùng phù hợp không
  3. a. Kịch bản được tìm thấy tại: ScrapeAndVote / RecognizeDennis.scr

1

Tốc độ tăng tốc lớn nhất mà tôi thường nhận được từ việc xây dựng các cam kết riêng biệt mà mỗi cam kết đại diện cho một bước trung gian biên dịch và hoạt động.

Vì vậy, nếu tôi phải giới thiệu một tham số mới cho một hàm để triển khai một tính năng cụ thể, thì có một cam kết không làm gì khác ngoài việc thêm tham số trong khai báo, trong định nghĩa và tại tất cả các trang web cuộc gọi. Sau đó, cam kết tiếp theo giới thiệu chức năng và lần thứ ba cập nhật các trang web cuộc gọi sử dụng tính năng mới.

Điều này rất dễ để xem xét, bởi vì những thay đổi hoàn toàn cơ học có thể được lướt qua nhanh chóng, và sau đó tránh ra.

Tương tự, nếu bạn định dạng lại mã, đó phải luôn là một cam kết riêng.


1

Mặc dù có một hoặc hai điểm bất đồng rõ ràng giữa các câu trả lời hiện có, nhưng nếu chỉ nhấn mạnh, tôi sẽ cố gắng tóm tắt lời khuyên thông thường theo cách làm rõ mọi người đến từ đâu:

  1. Thứ nhất, viết mã sạch; bất kỳ "tài liệu" nào khác sẽ tự chăm sóc bản thân sau đó. Mã sạch là một tập hợp các nguyên tắc cần học ở vị trí đầu tiên: các lớp trách nhiệm đơn, các phương thức ngắn thực hiện một việc, tên biến và tên phương thức tốt , tên lớp / loại tốt hơn so với các cách ẩn dụ (ví dụ: gọi MultiButtSupporter là soda), các bài kiểm tra đơn vị để chỉ ra các yêu cầu, DRY, RẮN, một mô hình nhất quán và như vậy.
  2. Mã tiết lộ cách mã hoạt động; ý kiến ​​tiết lộ lý do tại sao mã hoạt động. Ví dụ: giải thích +1 bằng "ngăn lỗi 1 lỗi" hoặc một số công thức phức tạp với "xuất phát trong sách giáo khoa hoặc trang web này".
  3. Bất cứ điều gì bạn đã làm với các bình luận, điểm 1 ở trên cũng có thể đạt được điều đó trong mã sạch. Xem bình luận là thất bại / tệ nạn cần thiết hoặc thậm chí là dối trá nếu theo thời gian chúng không đồng bộ với mã khi cả hai được chỉnh sửa. Nhận xét không nên bù cho mã được viết xấu, bởi vì tại sao các bình luận sẽ được viết với bất kỳ tài năng hoặc sự quan tâm nào hơn mã đó?

Mặt khác, nếu bất cứ điều gì tôi có thể sai quá xa theo cách khác, gần như không bao giờ sử dụng ý kiến. Người đánh giá mã của bạn sẽ cho bạn biết nếu bạn có số dư sai vị trí cho họ, nhưng nếu bạn nỗ lực có ý thức để thực hiện theo kế hoạch 3 điểm ở trên, bạn có thể sẽ ở gần mức tối ưu của họ.


2
Nhận xét "ngăn chặn lỗi 1 lỗi" khác với nhận xét "+1 không phải là lỗi chính tả" hay "Tôi không nhận ra lỗi do một lỗi trong chương trình của mình"? (Các nhận xét hữu ích thường liên quan đến thứ gì đó lớn hơn +1 trong mã nguồn hoặc với thứ gì đó bên ngoài mã nguồn.) Vì vậy, vẫn để "dẫn xuất trong sách giáo khoa hoặc trang web này" là một ví dụ hợp lệ và thực sự tuyệt vời trong quan điểm số 2 của bạn. Sau đó, điểm số 3 của bạn dường như gợi ý rằng bạn có thể thể hiện "xuất phát trong sách giáo khoa hoặc trang web này" bằng cách sử dụng mã đủ sạch mà không có bất kỳ nhận xét nào; wow, tôi muốn thấy điều đó trong hành động.
Jirka Hanika

@JirkaHanika Có lẽ off-by-one là một ví dụ tồi. Đối với 3, ý tôi là "mỗi có thể" chứ không phải "có thể mỗi"; vì vậy không, tôi không nghĩ rằng mã một mình có thể làm rõ những điều như vậy. (Chà, bạn có thể thử gaussianFrom ThisTextbookNamesAppro xấp xỉ như một tên biến, nhưng đó là một ý tưởng tồi!)
JG
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.