Làm thế nào để xác định mức độ trừu tượng


35

Tôi đã đọc một cuốn sách ngày hôm nay gọi là "Mã sạch" và tôi bắt gặp một đoạn văn là tác giả đang nói về mức độ trừu tượng cho một chức năng, ông đã phân loại một số mã là mức độ trừu tượng thấp / trung bình / cao.

Câu hỏi của tôi là các tiêu chí để xác định mức độ trừu tượng là gì?

Tôi trích dẫn đoạn từ cuốn sách:

Để đảm bảo các chức năng của chúng ta đang thực hiện một điều, một điều, chúng ta cần đảm bảo rằng các câu lệnh trong hàm của chúng ta đều ở cùng một mức độ trừu tượng. Thật dễ dàng để thấy cách Liệt kê 3-1 vi phạm quy tắc này. Có những khái niệm trong đó có mức độ trừu tượng rất cao, chẳng hạn như getHtml (); những cái khác ở mức độ trừu tượng trung gian, chẳng hạn như: String pagePathName = PathParser.render (pagePath); và vẫn còn các mức độ thấp đáng chú ý khác, chẳng hạn như: .append ("\ n").


Câu trả lời:


27

Tác giả giải thích rằng trong phần "Đọc mã từ trên xuống dưới" của phần nói về trừu tượng (mỏ thụt phân cấp):

[...] Chúng tôi muốn có thể đọc chương trình như thể nó là một tập hợp các đoạn TO , mỗi đoạn mô tả mức độ trừu tượng hiện tại và tham chiếu các đoạn TO tiếp theo ở cấp độ tiếp theo.

  • Để bao gồm các thiết lập và phân tích, chúng tôi bao gồm các thiết lập, sau đó chúng tôi bao gồm nội dung trang thử nghiệm và sau đó chúng tôi bao gồm các phân tích.
    • Để bao gồm các thiết lập, chúng tôi bao gồm thiết lập bộ nếu đây là bộ, sau đó chúng tôi bao gồm thiết lập thông thường.
      • Để bao gồm thiết lập bộ, chúng tôi tìm kiếm phân cấp cha mẹ cho trang "SuiteSetUp" và thêm một tuyên bố bao gồm với đường dẫn của trang đó.
        • Để tìm kiếm phụ huynh ...

Mã đi cùng với điều này sẽ giống như thế này:

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

Và như vậy. Mỗi khi bạn đi sâu hơn vào hệ thống phân cấp chức năng, bạn nên thay đổi mức độ trừu tượng. Trong ví dụ trên, IncludeSetups, IncludeTestPageContentIncludeTeardownstất cả đều ở cùng một mức độ trừu tượng.

Trong ví dụ được đưa ra trong cuốn sách, tác giả cho rằng hàm lớn nên được chia thành các phần nhỏ hơn rất cụ thể và chỉ làm một việc. Nếu được thực hiện đúng, hàm tái cấu trúc sẽ trông giống như các ví dụ ở đây. (Phiên bản được cấu trúc lại được đưa ra trong Liệt kê 3- 7 trong cuốn sách.)


10

Tôi nghĩ để hiểu câu hỏi này, bạn cần hiểu một sự trừu tượng là gì. (Tôi quá lười biếng để tìm một định nghĩa chính thức, vì vậy tôi chắc chắn rằng tôi sắp bị dìm, nhưng ở đây đi ...) Một sự trừu tượng là khi bạn lấy một chủ đề phức tạp, hoặc thực thể và ẩn hầu hết các chi tiết của nó trong khi phơi bày chức năng vẫn xác định bản chất của đối tượng đó.

Tôi tin rằng ví dụ cuốn sách đã cho bạn là một ngôi nhà. Nếu bạn nhìn vào ngôi nhà rất chi tiết, bạn sẽ thấy nó được làm từ ván, đinh, cửa sổ, cửa ra vào ... Nhưng một bản vẽ hoạt hình của một ngôi nhà bên cạnh một bức ảnh vẫn là một ngôi nhà, mặc dù nó bị thiếu nhiều chi tiết

Điều tương tự với phần mềm. Bất cứ khi nào bạn lập trình, giống như cuốn sách khuyên, bạn cần nghĩ về phần mềm của mình dưới dạng các lớp. Một chương trình nhất định có thể dễ dàng có hơn một trăm lớp. Ở phía dưới, bạn có thể có các hướng dẫn lắp ráp chạy trên CPU, ở cấp độ cao hơn, các hướng dẫn này có thể được kết hợp để tạo các thói quen I / O của đĩa, ở mức cao hơn, bạn không cần phải làm việc với Đĩa I / O trực tiếp vì bạn có thể sử dụng các chức năng của Windows để chỉ cần Mở / Đọc / Ghi / Tìm kiếm / Đóng tệp. Đây là tất cả các khái niệm trừu tượng ngay cả trước khi bạn nhận được mã ứng dụng của riêng bạn.

Trong mã của bạn, các lớp trừu tượng tiếp tục. Bạn có thể có các thói quen thao tác chuỗi / mạng / dữ liệu cấp thấp hơn. Ở cấp độ cao hơn, bạn có thể kết hợp các thường trình đó thành các hệ thống con xác định quản lý người dùng, lớp UI, truy cập cơ sở dữ liệu. Một lớp khác, các hệ thống con này có thể được kết hợp thành các thành phần máy chủ kết hợp lại để trở thành một phần của hệ thống doanh nghiệp lớn hơn.

Chìa khóa của mỗi lớp trừu tượng này là mỗi lớp ẩn các chi tiết được hiển thị bởi (các) lớp trước và trình bày một giao diện rất sạch sẽ được sử dụng bởi lớp tiếp theo. Để mở tệp, bạn không cần phải biết cách viết từng phần riêng lẻ hoặc phần cứng nào bị gián đoạn để xử lý. Nhưng nếu bạn bắt đầu di chuyển xuống chuỗi lớp trừu tượng, bạn chắc chắn sẽ có thể theo dõi từ lệnh gọi hàm Write (), đến tận hướng dẫn chính xác được gửi đến bộ điều khiển ổ cứng.

Những gì tác giả đang bảo bạn làm là khi bạn định nghĩa một lớp hoặc một hàm, hãy suy nghĩ về việc bạn là lớp nào. Nếu bạn có một lớp đang quản lý các hệ thống con và các đối tượng người dùng, thì cùng một lớp không nên thực hiện thao tác chuỗi mức thấp hoặc chứa một loạt các biến chỉ để thực hiện các cuộc gọi socket. Đó sẽ là vi phạm của việc vượt qua các lớp trừu tượng và cũng có một lớp / chức năng chỉ làm một việc (SRP - Nguyên tắc trách nhiệm duy nhất).


2

Câu hỏi của tôi là các tiêu chí để xác định mức độ trừu tượng là gì?

Mức độ trừu tượng được cho là rõ ràng. Thật trừu tượng nếu đó là một phần của miền vấn đề - không phải là một phần của ngôn ngữ lập trình. Thật khó để rõ ràng hơn "rất trừu tượng" == "không có thật" == "miền vấn đề". Và "không trừu tượng == Concrete == một phần của ngôn ngữ". Nó được coi là tầm thường để quyết định mức độ trừu tượng. Không có bất kỳ sự tinh tế nào cả.

.append("\n")không trừu tượng. Nó chỉ đặt một ký tự lên một chuỗi. Đó sẽ là cụ thể. Không trừu tượng.

String pagePathName = PathParser.render(pagePath);giao dịch với chuỗi. Những thứ cụ thể. Một phần về các tính năng ngôn ngữ lập trình cụ thể. Làm việc một phần với các khái niệm "đường dẫn" và "trình phân tích cú pháp" trừu tượng.

getHtml(); Trừu tượng. Giao dịch với "Đánh dấu" và những thứ không tầm thường, cụ thể, các tính năng ngôn ngữ.

Tóm tắt == không phải là một tính năng ngôn ngữ.

Cụ thể == một tính năng ngôn ngữ.


1
Nếu bạn định nghĩa trừu tượng là một chất lượng mô tả những thứ mà lập trình viên tạo ra, tức là trừu tượng do lập trình viên tạo ra, thì tôi có khuynh hướng đồng ý với các định nghĩa từ của bạn. Nhưng tất cả các ngôn ngữ lập trình là trừu tượng hơn một cái gì đó cụ thể hơn. Sự lựa chọn của ngôn ngữ lập trình xác định, ở một mức độ lớn, mức độ trừu tượng mà bạn bắt đầu ở mức nào.
Robert Harvey

1

Tôi nghĩ mức độ trừu tượng là đơn giản ... nếu dòng mã không trực tiếp thực hiện trách nhiệm duy nhất của phương thức, thì đó là một mức độ trừu tượng khác. Ví dụ: nếu tên phương thức của tôi là SaveChangedCustomers () và lấy danh sách TẤT CẢ khách hàng làm tham số, thì trách nhiệm duy nhất là lưu bất kỳ khách hàng nào trong danh sách đã được thay đổi:

foreach(var customer in allCustomers)
{
    if (CustomerIsChanged(customer)
        customer.Save();
}

Thông thường, thay vì gọi phương thức CustomerIsChanged (), bạn sẽ tìm thấy logic để xác định xem khách hàng có thay đổi được nhúng trong vòng lặp foreach không. Xác định xem hồ sơ khách hàng đã thay đổi KHÔNG phải là trách nhiệm của phương pháp này! Đó là một mức độ trừu tượng khác nhau. Nhưng nếu logic để đưa ra quyết định đó chỉ là một dòng mã thì sao? Nó không thành vấn đề !!! Đó là một mức độ trừu tượng khác nhau và cần phải nằm ngoài phương pháp này.

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.