Xử lý món súp giòn


11

Tôi đã lập trình trong cả C # và VB.NET trong nhiều năm, nhưng chủ yếu là VB. Tôi đang chuyển hướng nghề nghiệp sang C # và nói chung, tôi thích C # hơn.

Tuy nhiên, một vấn đề tôi gặp phải là súp giòn. Trong VB, mỗi từ khóa cấu trúc có một từ khóa đóng phù hợp, ví dụ:

Namespace ...
    Class ...
        Function ...
            For ...
                Using ...
                    If ...
                        ...
                    End If
                    If ...
                        ...
                    End If
                End Using
            Next
        End Function
    End Class
End Namespace

Mã tương tự được viết bằng C # kết thúc rất khó đọc:

namespace ... {
    class ... {
        function ... {
            for ... {
                using ... {
                    if ... {
                        ...
                    }
                    if ... {
                        ...
                    }
                }
            }
            // wait... what level is this?
        }
    }
}

Đã quá quen với VB, tôi tự hỏi liệu có một kỹ thuật được sử dụng bởi các lập trình viên kiểu c để cải thiện khả năng đọc và để đảm bảo rằng mã của bạn kết thúc trong "khối" chính xác. Ví dụ trên tương đối dễ đọc, nhưng đôi khi ở cuối đoạn mã tôi sẽ có 8 cấp độ niềng răng xoăn trở lên, yêu cầu tôi cuộn lên nhiều trang để tìm ra dấu ngoặc nào kết thúc khối mà tôi quan tâm trong.


83
Tôi biết điều này nghe có vẻ khó hiểu và có thể bạn có những điều kiện đặc biệt cần đến nó (vì vâng, đôi khi nó là cần thiết - rất may là những lần như vậy rất hiếm), nhưng thường là "... 8 hoặc nhiều cấp độ của niềng răng xoăn, yêu cầu tôi phải cuộn lên một vài trang để tìm ra cái nẹp nào kết thúc khối mà tôi quan tâm " có nghĩa là mã cần một số tái cấu trúc và dọn dẹp nghiêm trọng.
Thất vọngWithFormsDesigner

7
Một điều tôi đã thấy và tôi đã thực hiện, là ở phần cuối của một cái nẹp xoăn, tôi sẽ thêm một nhận xét về nó. Một cái gì đó như // End's using X statement.
PiousVenom

14
@FrustratedWithFormsDesigner phát hiện ra về thực tế rằng luồng kiểm soát của bạn là một mớ hỗn độn và cần phải được làm lại. Điều đó nói rằng, tôi nghĩ rằng bạn đang phàn nàn về niềng răng xoăn hơn là phạm vi và tôi sẽ nói bạn chỉ cần làm quen với nó. Học một ngôn ngữ với cú pháp khác biệt đáng kể so với việc bạn sử dụng để chắc chắn trông giống như súp trong một thời gian, nhưng thực tế sẽ biến mất. Bạn chỉ cần khóa xuống và giải quyết cho đến khi bộ não của bạn bắt đầu xử lý cú pháp một cách tự nhiên hơn, bạn sẽ đến đó.
Jimmy Hoffa

2
@FrustratedWithFormsDesigner - Tôi cần dọn dẹp rất nhiều đối tượng COM trong tình huống xen kẽ COM. Tôi đang sử dụng kỹ thuật được đề xuất trong bài viết này: jake.ginnivan.net/vsto-com-interop . Điều này dễ dàng tạo ra hai hoặc ba lớp. Khi bạn xếp chồng vòng lặp for, hàm, lớp và không gian tên lên trên đó (cùng với câu lệnh if), bạn dễ dàng có được một vài lớp dấu ngoặc.
JDB vẫn còn nhớ Monica

5
@TyrionLannister - Và đó có thể là một số bình luận nhanh nhất không đồng bộ với những gì họ thuộc về ... Tôi nghĩ rằng nếu tôi sẽ có một cái gì đó như thế, tôi muốn nó được tạo tự động (hiển thị -Chỉ thời gian, không tồn tại) bởi IDE.
Clockwork-Muse

Câu trả lời:


38

Đặt nẹp xoăn bắt đầu của bạn trong cùng một "thứ hạng" như kết thúc của bạn, như thế này:

namespace ... 
{
    class ... 
    {
        function ... 
        {
            for ... 
            {
                using ... 
                {
                    if ... 
                    {
                        ...
                    }
                    if ... 
                    {
                        ...
                    }
                }
            }
            // It's the `function` level!
        }
    }
}

15
Tôi đồng ý. Dấu ngoặc Ai Cập làm tôi đau đầu.
PiousVenom

8
Ngoài ra, hầu hết các IDE (có thể) làm nổi bật đối tác của niềng răng khi bạn nhấp vào nó.
StuperUser

3
@TyrionLannister: Cảm ơn vì cuối cùng đã cho tôi một thuật ngữ cho phong cách đó! Tôi chưa bao giờ có một cái tên hay cho họ ngoài "niềng răng sai lệch".
Thất vọngWithFormsDesigner

3
@ Cyborgx37: IDE của bạn có tính năng "Chuyển đến khớp nối" không? Thường bị ràng buộc với một phím tắt tự động di chuyển con trỏ của bạn đến dấu ngoặc khớp với phím tắt hiện được tô sáng.
Thất vọngWithFormsDesigner

3
Gotta nói, tôi không thấy làm thế nào điều này làm cho nó dễ dàng hơn. Dù bằng cách nào, bạn chỉ cần nhìn lên màn hình ở cấp độ thụt của nẹp cho đến khi bạn nhận được một từ khóa. Và với tất cả những dòng thêm bạn bây giờ có thêm để xem xét.
Blorgbeard ra khỏi

14
  • Tùy thuộc vào IDE của bạn: đặt con trỏ của bạn ở nẹp mở / đóng và nó sẽ làm nổi bật cả dấu ngoặc đó và dấu ngoặc tương ứng.
  • Thu gọn khối và nó cho bạn thấy nơi nó mở / đóng.
  • Viết các khối mã nhỏ hơn. Nghiêm túc. Kiểm tra Clean Codevà không bao giờ gặp phải vấn đề này nữa (và có mã dễ đọc / dễ bảo trì hơn).

Một lưu ý, sau đây là cú pháp c # hợp lệ có thể giúp ích cho tình huống cụ thể của bạn:

using (var type = new MyDisposable1())
using (var type2 = new MyDisposable2())
{
    /* do what you will with type2 and type2 */
}

Săn lùng nhân vật nổi bật duy nhất là điều khiến tôi phải đặt câu hỏi này ngay từ đầu.
JDB vẫn còn nhớ Monica

2
@ Cyborgx37: Do đó điểm 3. Nếu toàn bộ khối mã của bạn vừa với màn hình, bạn không bao giờ phải săn. Trong hầu hết / tất cả các lớp tôi viết, các cặp dấu ngoặc duy nhất không vừa trên màn hình là không gian tên / lớp.
Steven Evers

Những gì bạn đề xuất ở điểm 1 & 2 là những gì tôi làm bây giờ ... nhưng điều này yêu cầu tôi rời khỏi nơi tôi đang mã hóa và bắt đầu thao túng cách nhìn của tôi về mã để tìm ra nơi đặt dòng tiếp theo. Điểm 3 được thực hiện tốt, nhưng không phải lúc nào cũng có thể, đặc biệt là nếu mã của bạn yêu cầu một số lớp usingkhối (xem jake.ginnivan.net/vsto-com-interop )
JDB vẫn còn nhớ Monica

@ Cyborgx37: Xem chỉnh sửa của tôi.
Steven Evers

1
@ Cyborgx37 Nếu bạn chọn một màu nổi bật so với mọi thứ khác (tôi đã sử dụng nền màu tím và văn bản màu trắng trong một thời gian, IIRC) thì không cần phải tìm kiếm niềng răng phù hợp - thực tế nó CHẮC CHẮN với bạn " TÔI Ở ĐÂY ! ".
một CVn

5

Một quy ước chung là thêm một nhận xét sau dấu ngoặc nhọn để chỉ ra cấu trúc mà nó đóng:

if {
   ...
} // end if

while (condition) {
   ...
} // end while

vv Tôi đã không bao giờ ấm áp với hội nghị này bản thân mình, nhưng một số người thấy nó hữu ích.


16
Tôi đã thấy mọi người làm điều này và khi họ trao đổi / thay đổi sự khởi đầu của khối (thay đổi whilethành a for, hoán đổi thành ifcâu lệnh), họ gần như KHÔNG BAO GIỜ nhớ cập nhật các bình luận đóng, khiến chúng tệ hơn vô dụng. Quy ước này có lẽ sẽ chỉ hữu ích nếu bạn có thể buộc bản thân duy trì các bình luận mỗi khi bản chất của các {thay đổi phù hợp .
Thất vọngWithFormsDesigner

Vâng, tôi đã thực hiện một số điều này, nhưng đó là rất nhiều công việc phụ (và tiếng ồn). Tôi đã hy vọng sẽ có một cái gì đó đơn giản hơn.
JDB vẫn còn nhớ Monica

5
Nhận xét chỉ nên giải thích lý do tại sao không bao giờ những gì hoặc làm như thế nào khi mã đó làm cả hai và dựa vào nhận xét để giải thích một trong số chúng có nghĩa là mã khó đọc, đó là một dấu hiệu mã nên được sửa không được bình luận.
Jimmy Hoffa

1
Điều này khiến tôi tự hỏi tại sao không ai viết một trình soạn thảo hiển thị những bình luận này, nhưng thực tế không bao gồm chúng trong mã ..
Brendan Long

2
@JimmyHoffa: Tôi nghĩ một quy tắc tốt hơn cho các bình luận là họ nên cung cấp sự rõ ràng . Thông thường điều đó có nghĩa là trả lời "tại sao", nhưng nó cũng có thể có nghĩa là những thứ khác. Đừng để bị cuốn vào giáo điều đến mức nó ngăn bạn làm những việc thực sự có ích, chẳng hạn như thỉnh thoảng thêm một bình luận cho một cú đúp đóng cách xa với cú đúp mở đầu của nó.
Bryan Oakley

5

Nói chung, khi khó kết hợp niềng răng theo bất kỳ phong cách nào - điều đó có thể có nghĩa là phương pháp này quá dài và nên được áp dụng lại.


5

Tôi nghĩ rằng bạn cần phải cứng rắn với niềng răng. Cuối cùng, chúng sẽ trở thành bản chất thứ hai đối với bạn và bạn sẽ tự hỏi làm thế nào bạn sống mà không có chúng.

Hãy chắc chắn rằng chúng được thụt lề một cách thích hợp, và một số quy ước khoảng cách đang được tuân theo (không quan trọng).


Một năm sau, và lời khuyên này đúng. :)
JDB vẫn còn nhớ Monica

4

Tôi loại bỏ 2 cấp độ lồng nhau bằng cách thu gọn không gian tên và phạm vi lớp theo chiều ngang. Lưu ý các phương thức được tuôn ra với cạnh trái của màn hình. Tôi không thấy điểm mất 2 cấp độ thụt trong mỗi tệp.

Sau đó, hiếm khi bạn làm tổ sâu hơn 4 cấp.

namespace FooNameSpace {
class Foo {

public void bar()
{
    while(true)
    {
        while(true)
        {
            break;
        }
    }
}

public void fooBar()
{
    foreach(var item in FooList)
    {
        foreach(var b in item.Bars)
        {
            if(b.IsReady)
            {
                bar();
            }
            bar();
        }
        bar();
    }
}

}}//end class, namespace

Tôi thích ý tưởng này, nhưng Visual Studio dường như không hỗ trợ nó (ít nhất là năm 2008, chúng tôi sẽ nâng cấp lên 2012 vào cuối năm nay, vì vậy, đây là hy vọng)
JDB vẫn còn nhớ đến

@ Cyborgx37. Tôi chỉnh sửa văn bản bên ngoài trong VIM để nó không thành vấn đề. Nhưng trong Visual Studio làm: Control + A, sau đó nhấn nút "indent less". Chỉ làm điều đó cho các tập tin mới. Đừng bận tâm với các tệp hiện có vì nó sẽ làm rối tung các so sánh khác nhau trong kiểm soát nguồn.
mike30

Nhập vào dấu ngoặc / dấu ngoặc nhọn khởi tạo định dạng tự động bằng VS nhưng bạn luôn có thể nhấn CTRL + z để từ chối đề xuất của nó.
Alex Tại Paris

1

Gần đây tôi đã quyết định thử và chính thức hóa hai quy tắc về các cấu trúc kiểm soát dòng chảy về cơ bản như sau:

  • Bạn không nên có gì ngoài các cấu trúc dòng mã cần thiết
  • Bạn nên làm cho các cấu trúc dòng mã càng nhỏ càng tốt

Đối với chính xác những lý do bạn đã đề cập và nhận thức rõ ràng, tôi nghĩ đây là những quy tắc tuyệt vời để tuân theo. Có một vài kỹ thuật đơn giản bạn có thể sử dụng để thực hiện chúng:

  • Thoát khỏi phạm vi ngay khi bạn có thể (điều này bao gồm phạm vi của các vòng lặp cũng như các chức năng)
  • Theo dõi các elses có thể được giảm thiểu bằng cách thoát khỏi hàm trước đó và áp dụng kỹ thuật thoát phạm vi như tôi đã đề cập
  • Đảo ngược kiểm tra có điều kiện của bạn khi mã bên trong nếu lớn hơn bên ngoài
  • Mã yếu tố bên trong một vòng lặp ra một phương thức khác khi kích thước của vòng lặp phát triển để che khuất phần còn lại của phương thức
  • Theo dõi bất kỳ phạm vi nào chỉ chứa phạm vi khác, ví dụ, một hàm có toàn bộ phạm vi được điền bởi một if không có gì ngoài if

Tôi đã nêu chi tiết ở đây các ví dụ về cách không tuân theo những điều này có thể khiến bạn làm như bạn đã nói và đặt mã vào khối mã sai, điều này rất tệ và là nguyên nhân dễ gây ra lỗi trong quá trình bảo trì.


Cảm ơn, có thể có một hoặc hai khối mà tôi có thể tái cấu trúc. Nó sẽ giúp, nhưng thật khó để cấu trúc lại một số usingkhối lồng nhau .
JDB vẫn còn nhớ Monica

@ Cyborgx37 thực sự sử dụng các khối có thể được nội tuyến nếu chúng được lồng hoàn thành các phạm vi, hãy xem tại đây stackoverflow.com/questions/1329739/. Nó về cơ bản hoạt động giống như các điều khiển dòng đơn xây dựng cách bạn có thể nếu (true) doS Something (); bạn cũng có thể if (true) if (SomethingElse) if (otherThings) {do This (); làm vậy đi(); làm bất cứ điều gì(); } và ifs làm tổ như bạn mong đợi (ĐỪNG VIẾT MÃ SỐ THÍCH NHƯ VẬY CHO TÌNH YÊU CỦA THIÊN CHÚA, CHỈ LÀM ĐIỀU NÀY VỚI VIỆC SỬ DỤNG VÀ KHÔNG CÓ ELSE heh)
Jimmy Hoffa

Vâng, tôi biết về việc lồng nhau bằng cách sử dụng các khối, nhưng điều này chỉ hoạt động nếu bạn có một dòng duy nhất bên dưới. Trong hầu hết các mã của tôi, đó không phải là trường hợp. Vẫn là một bài viết rất hữu ích về tổng thể ... đã học được một số điều (+1)
JDB vẫn còn nhớ Monica

@ Cyborgx37 yeah Tôi nhận ra phạm vi lồng nhau chỉ hoạt động khi bạn không có thêm bit, điều đó có nghĩa là cách sử dụng của bạn không? Có lẽ sẽ khả thi khi chuyển một phần bổ sung đó vào nhà xây dựng nếu nó ở trên đỉnh hoặc xử lý nếu nó ở dưới cùng? Đó là nếu nó theo khuôn mẫu; đoán có thể là do bạn đã đưa ra vấn đề này, vì vậy bạn có thể gặp phải những vấn đề này bằng cách sử dụng các tổ thường xuyên trong mã của bạn.
Jimmy Hoffa

Tôi thực sự đã bắt đầu công việc triển khai mô hình Nhà máy bao bọc các đối tượng COM trong lớp "AutoCleanup". Sau đó tôi sử dụng một usingcâu lệnh trên lớp nhà máy và khi được xử lý, nó sẽ tự động loại bỏ tất cả các lớp được gói. Nó hoạt động tốt cho đến nay và đã giảm đáng kể số lượng usingbáo cáo trong mã của tôi.
JDB vẫn còn nhớ Monica

1

Thật không may, đây là một trong những nguyên nhân lâu đời nhất của chiến tranh trong điện toán. Có thể đưa ra những lý lẽ hợp lý từ cả hai phía (nền kinh tế bất động sản theo chiều dọc tốt hơn so với khả năng dễ dàng hơn để khớp trực quan với cú đúp mở), nhưng trong thực tế, một trình định dạng mã nguồn đơn giản sẽ giải quyết mọi thứ cho bạn. MS Visual C # có một tích hợp hoạt động tốt.

Tuy nhiên, được cảnh báo rằng nếu bạn đang làm việc như là một phần của một nhóm, bạn sẽ phải tuân thủ các quy ước được sử dụng bởi nhóm đó, do đó, bạn phải trả tiền để làm quen với cả hai phong cách và không được tôn giáo theo kiểu niềng răng.

Vì vậy, trong khi bạn đang học bằng mọi cách có nghĩa là tập trung vào phong cách giúp bạn dễ học hơn, nhưng hãy để mắt đến người khác trong khi bạn ở đó và bạn sẽ làm tốt.


1
Tôi không chắc đó là trình định dạng mặc định hay thứ gì đó trong ReSharper, nhưng khi tôi sử dụng C #, chúng tôi có một tùy chọn được định dạng lại mã là một phần của đăng ký. Bằng cách đó, bạn có thể định dạng mã theo cách bạn muốn trong khi bạn đang làm việc với nó, nhưng nó sẽ được định dạng lại thành "tiêu chuẩn dự án" khi đăng ký. Tôi nghĩ rằng tiêu chuẩn định dạng thực sự duy nhất chúng tôi có là sử dụng khoảng trắng thay vì các tab.
TMN

1

Sử dụng Resharper, sẽ giúp đề xuất các cách để giảm lồng. Ngoài ra, hãy đọc cuốn sách Clean Code của Bob Martin , trong đó nhấn mạnh rằng một chức năng chỉ nên làm một việc, và do đó mỗi chức năng chỉ nên dài nửa tá dòng, vì vậy bạn sẽ không phải lo lắng về nhiều cấp độ.


1

Có một tiện ích bổ sung cho trình chỉnh sửa có thể giúp bạn tại: C # Outline .

Tiện ích mở rộng trình soạn thảo VS20xx cho C # bằng cách thêm các tính năng để thu gọn, mở rộng và làm nổi bật các khối mã lồng nhau. Các tính năng này cho phép chỉnh sửa và đọc nội dung lồng nhau của các khối mã dễ dàng hơn như if, while, v.v.


0

Nếu bạn viết Mã của mình trong Visual Studio, thì cũng có một Plugin hiển thị cho bạn các dấu chấm dọc giữa điểm đầu và điểm cuối của mọi cấu trúc mà bạn xây dựng.

Nhưng nhìn chung, tôi nghĩ rằng sẽ mất một chút thời gian cho đến khi bạn quen với "xoăn-niềng-súp". (Btw, tôi thực sự thích biểu hiện đó. Nghe có vẻ giống như một Tên Tập cho Lý thuyết Vụ nổ lớn)


0

Sự thụt lề cho bạn biết bạn đang ở đâu, trong cả hai kiểu cú pháp. Nếu bạn viết chương trình VB hoặc chương trình C # trên một dòng, bạn sẽ sớm không thể biết được bạn đang ở đâu trong cú pháp lồng nhau. Máy phân tích các cụm từ kết thúc khối hoặc dấu ngoặc nhọn, nhưng con người cần thụt lề.

Các cụm từ kết thúc xuất phát từ một kỷ nguyên của thẻ đục lỗ và băng giấy, khi lập trình ít tương tác và trực quan hơn nhiều. Hoặc, thực sự, không tương tác chút nào. Rất khó để vào các chương trình, và vì vậy các lập trình viên cần trình biên dịch phải rất thông minh về phân tích cú pháp và phục hồi lỗi.

Trong thời đại đã qua, chu trình biên dịch-biên dịch có thể liên quan đến việc chuẩn bị thẻ đục lỗ bằng máy bấm thẻ, sau đó xếp hàng vào cửa sổ nộp công việc trong đó một nhân viên lấy thẻ đục lỗ và gửi chúng vào máy. Sau đó, lập trình viên sẽ thu thập đầu ra (in trên giấy) từ một cửa sổ khác. Nếu chương trình có lỗi, đầu ra sẽ chỉ bao gồm chẩn đoán trình biên dịch. Khi thời gian quay vòng dài, chi phí gõ end ifthay vì chỉ )là hợp lý nếu nó giúp cải thiện chất lượng chẩn đoán, bởi vì lập trình viên cần sửa càng nhiều lỗi càng tốt trong một lần lặp để giảm số lần lãng phí thời gian lặp đi lặp lại qua cửa sổ trình công việc.

Khi thiếu một nẹp xoăn đóng, thật khó để biết niềng răng mở nào là không được đóng. (Trình biên dịch có thể phải phân tích thụt lề để đưa ra phỏng đoán có giáo dục.) Nếu bạn xóa một dấu ngoặc đóng bên trong một hàm, thì có vẻ như toàn bộ phần còn lại của tệp là một phần của hàm đó, dẫn đến một loạt các thông báo lỗi không hữu ích. Trong khi nếu bạn có một end functioncú pháp, trình biên dịch có thể suy ra nơi hàm bị lỗi kết thúc, phục hồi và phân tích các hàm tiếp theo đúng cách, cung cấp cho bạn chẩn đoán bổ sung, nếu có, có ý nghĩa.

Khi bạn đang làm việc trong trình soạn thảo văn bản nhận biết mã tự động thụt lề và tô màu mã của bạn, trên màn hình độ phân giải cao nơi bạn có thể thấy sáu mươi dòng trở lên, các đối số cho các loại ngôn ngữ vụng về đó không còn được áp dụng. Bạn có thể dần dần chỉnh sửa và xây dựng lại các chương trình nhanh đến mức bạn chỉ có thể xử lý một lỗi tại một thời điểm. Hơn nữa, bằng cách xem các phần lớn của chương trình đồng thời trên màn hình và duy trì thụt lề thích hợp, bạn có thể giảm sự xuất hiện của các loại lỗi lồng nhau đó ngay từ đầu. Và trình soạn thảo văn bản lập trình tốt thậm chí sẽ gắn cờ một số loại lỗi cú pháp khi bạn nhập. Hơn nữa, có các trình soạn thảo gấp sẽ thu gọn các khối của chương trình dựa trên cú pháp của nó, đưa ra một khung nhìn "giống như phác thảo" về cấu trúc của nó.

Lisp đã sử dụng dấu ngoặc đơn ngay từ đầu và có lẽ, không phải ngẫu nhiên, tin tặc Lisp đã tiên phong lập trình như một trải nghiệm tương tác bằng cách xây dựng các hệ thống chấp nhận các chương trình trong các đoạn nhỏ (biểu thức).

Thực tế, bạn hoàn toàn không cần biểu tượng kết thúc, như ngôn ngữ Python minh họa. Việc xác định chỉ có thể là cấu trúc. Con người đã sử dụng thụt lề để mò mẫm cấu trúc mã ngay cả trong các ngôn ngữ mà máy phụ thuộc vào các ký hiệu hoặc cụm từ kết thúc.


-1

Nếu bạn đang sử dụng IDE, chỉ cần nhấn Crtl+ k+ Dvà IDE sẽ thực hiện phần còn lại của công việc.


Nhật thực IDE sử dụng ctrl-shift-i để thụt lề và ctrl-shift-f để định dạng
ratchet freak

kiểm tra trong phòng thu trực quan
Jagz W
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.