Những gì trừu tượng sớm là gì?


10

Tôi đã nghe thấy cụm từ bị ném lên và đối với tôi, những cuộc tranh luận nghe có vẻ hoàn toàn điên rồ (xin lỗi nếu tôi là người rơm ở đây, đó không phải là ý định của tôi), nói chung nó đi theo hướng:

Bạn không muốn tạo ra một sự trừu tượng trước khi bạn biết trường hợp chung là gì, nếu không (1) bạn có thể đặt những thứ trừu tượng không thuộc về mình, hoặc (2) bỏ qua những điều quan trọng.

(1) Đối với tôi điều này nghe có vẻ như lập trình viên không đủ thực dụng, họ đã đưa ra giả định rằng mọi thứ sẽ tồn tại trong chương trình cuối cùng không có, vì vậy họ đang làm việc với mức độ trừu tượng thấp, vấn đề không phải là trừu tượng sớm, đó là sự lắng đọng sớm.

(2) Bỏ qua những thứ quan trọng là một điều, hoàn toàn có thể một thứ gì đó được bỏ qua từ thông số mà sau này hóa ra lại quan trọng, giải pháp cho vấn đề này không phải là đưa ra sự lãng phí và lãng phí tài nguyên của chính bạn khi bạn phát hiện ra bạn đoán sai, đó là để có thêm thông tin từ khách hàng.

Chúng ta nên luôn luôn làm việc từ trừu tượng xuống cụ thể vì đây là cách làm việc thực dụng nhất, và không phải là cách khác.

Nếu chúng ta không làm như vậy thì chúng ta có nguy cơ hiểu nhầm khách hàng và tạo ra những thứ cần phải thay đổi, nhưng nếu chúng ta chỉ xây dựng sự trừu tượng mà khách hàng đã xác định bằng ngôn ngữ của họ, chúng ta sẽ không bao giờ gặp rủi ro này (ít nhất là không có khả năng như một cú đánh trong bóng tối với một chút thận trọng), vâng, có thể khách hàng thay đổi suy nghĩ về các chi tiết, nhưng những điều trừu tượng họ sử dụng để truyền đạt những gì họ muốn có xu hướng vẫn còn hiệu lực.

Dưới đây là một ví dụ, giả sử khách hàng muốn bạn tạo robot đóng gói vật phẩm:

public abstract class BaggingRobot() {
    private Collection<Item> items;

    public abstract void bag(Item item);
}

Chúng tôi đang xây dựng một cái gì đó từ sự trừu tượng mà khách hàng đã sử dụng mà không đi sâu vào chi tiết hơn với những điều chúng tôi không biết. Điều này cực kỳ linh hoạt, tôi đã thấy điều này được gọi là "trừu tượng sớm" khi trong thực tế, sẽ sớm hơn để giả định cách thức đóng gói được thực hiện, giả sử sau khi thảo luận với khách hàng, họ muốn có nhiều hơn một mặt hàng được đóng gói cùng một lúc . Để cập nhật lớp học của tôi, tất cả những gì tôi cần là thay đổi chữ ký, nhưng đối với một người bắt đầu từ dưới lên có thể liên quan đến việc đại tu hệ thống lớn.

Không có thứ gọi là trừu tượng sớm, chỉ có sự lắng đọng sớm. Điều gì là sai với tuyên bố này? Đâu là sai sót trong lý luận của tôi? Cảm ơn.


1
Trái ngược với sự trừu tượng quá sớm là YAGNI - Bạn không cần nó, mà theo tôi thì hầu như luôn luôn sai. Hầu hết. Tôi đã thấy nó xảy ra, nhưng nó hiếm. Tôi hầu hết đồng ý với những gì bạn nói ở đây.
dùng1118321

Câu trả lời:


19

Ít nhất theo ý kiến ​​của tôi, sự trừu tượng sớm là khá phổ biến, và đặc biệt là rất sớm trong lịch sử của OOP.

Ít nhất là từ những gì tôi thấy, vấn đề chính nảy sinh là mọi người đọc qua các ví dụ điển hình của hệ thống phân cấp hướng đối tượng. Họ đã nói rất nhiều về việc làm cho mọi thứ sẵn sàng để đối phó với những thay đổi trong tương lai có thể phát sinh (mặc dù không có lý do đặc biệt tốt để tin rằng họ sẽ làm). Một chủ đề khác phổ biến cho nhiều bài báo trong một thời gian là những thứ như thú mỏ vịt, bất chấp các quy tắc đơn giản về "động vật có vú đều như thế này" hoặc "tất cả các loài chim đều như vậy".

Kết quả là, chúng tôi đã kết thúc với mã thực sự chỉ cần xử lý, ví dụ, hồ sơ của nhân viên, nhưng được viết cẩn thận để sẵn sàng nếu bạn từng thuê một con arachnid hoặc có thể là một loài giáp xác.


Vì vậy, trừu tượng hóa sớm không phải là hành động trừu tượng hóa, đó là hành động trừu tượng hóa vượt quá mức độ trừu tượng của thông số kỹ thuật. Điều đó có ý nghĩa hơn rất nhiều, và tôi có thể thấy điều đó thực sự xảy ra. Tôi đoán tôi chỉ cần nói rõ hơn với các đồng nghiệp của mình rằng tôi đang làm việc ở mức độ trừu tượng được vạch ra bởi người quản lý của tôi.
James

1
@James: cũng có nghĩa là trừu tượng "quá nhiều" vì thông số kỹ thuật của phiên bản 1.0, vì bạn tin rằng bạn biết một yêu cầu mới trong thông số của phiên bản mới hơn, do đó đã triển khai v1.0 theo cách tổng quát hơn cần thiết. Đôi khi, thật tốt khi hình dung những gì có thể xảy ra trong phiên bản sau, nhưng cũng có một rủi ro nhất định về sự áp đảo.
Doc Brown

@DocBrown Tôi sẽ gọi đó là sự lắng đọng sớm. Hành động trừu tượng là loại bỏ các mẩu thông tin, không thêm chúng. Nếu bạn đang thêm nhiều hơn vào sự trừu tượng hơn mức cần thiết thì bạn đang giả định điều gì đó về mức độ trừu tượng thấp hơn. Tôi muốn phân biệt giữa hai điều này vì tôi nghĩ rằng việc gọi là "trừu tượng hóa" không có ý nghĩa gì nhiều vì định nghĩa của trừu tượng hóa là "quá trình rút ra bản chất cơ bản" Trường hợp như sự lắng đọng "được đặc trưng bởi hoặc thuộc về kinh nghiệm tức thời của những điều thực tế hoặc sự kiện ".
James

6

Điều quan trọng cần nhớ là sự trừu tượng là một phương tiện để kết thúc. Bạn sử dụng sự trừu tượng hóa để thống nhất hành vi trong chương trình của mình và thực hiện việc bổ sung các lớp mới một cách đơn giản trong trường hợp bạn muốn các lớp mới được thêm vào nhưng chỉ khi sự trừu tượng là cần thiết trong thời điểm đó.

Bạn sẽ không thêm trừu tượng chỉ vì bạn có thể cần nó (không có cơ sở thực sự để nghĩ rằng bạn sẽ cần thêm các lớp mới trong tương lai). Một phép ẩn dụ thích hợp ở đây có thể là hệ thống ống nước. Hy vọng rằng bạn sẽ đồng ý rằng một đường ống 6 hướng cho phép nước chảy lên / xuống, đông / tây, bắc / nam sẽ là loại ống linh hoạt nhất bạn có thể có. Về mặt lý thuyết, bạn có thể sử dụng đường ống 6 hướng ở bất cứ nơi nào cần ống, và chặn các hướng không cần thiết, phải không?

Nếu bạn đã cố gắng khắc phục sự cố rò rỉ dưới bồn rửa của mình và thấy tất cả các phần của ống là các đoạn ống 6 hướng, bạn sẽ muốn nhổ tóc ra vì thất vọng với anh chàng đã thiết kế nó theo cách đó. Bạn không chỉ không biết vấn đề ở đâu, mà gần như chắc chắn sẽ đơn giản hơn nếu chỉ bắt đầu từ đầu được thực hiện một cách thích hợp.

Tất nhiên mã hóa không phải là hệ thống ống nước, nhưng ẩn dụ vẫn đứng vững. Trừu tượng giống như sử dụng các mảnh ống 6 hướng. Sử dụng chúng khi bạn thành thật tin rằng một ngày nào đó trong tương lai gần bạn cần kết nối các đường ống từ tất cả 6 hướng. Mặt khác, sự trừu tượng chỉ đơn giản là sự phức tạp, không khác nhiều so với việc sử dụng một mô hình trong đó không yêu cầu hoặc sử dụng một lớp thần cố gắng làm mọi thứ. Nếu nó không được sử dụng và sẽ không bao giờ được sử dụng, cuối cùng bạn sẽ thêm một lớp bổ sung mà không có gì.

Phải thừa nhận rằng, nghệ thuật viết chương trình rất khái niệm rất trừu tượng. Đơn giản chỉ cần đề cập rằng trừu tượng không tồn tại vì mục đích trừu tượng mà vì chúng thực tế theo một cách thực tế nào đó. Nếu bạn cảm thấy cần phải sử dụng sự trừu tượng, thì cũng vậy, nhưng đừng yêu cầu tôi kiểm tra hệ thống ống nước của bạn sau đó. ;)


Bạn có vẻ là một người lập classdị một chút Ngay cả khi có nhiều lớp, sự trừu tượng không bị giới hạn để được sử dụng trong / mang lại lợi ích cho họ.
Ded repeatator

1
@Ded repeatator Đủ công bằng, nhưng điều đó không thay đổi quan điểm của tôi. Nếu sự trừu tượng được sử dụng, nó sẽ có lợi ngay lập tức hoặc nó sẽ là một sự thay đổi có kế hoạch trong tương lai gần. Vấn đề không phải là chúng ta đang đề cập đến các lớp học hoặc lập trình chức năng.
Neil

3

Khi tôi tìm hiểu về Phân tích và Thiết kế hướng đối tượng, nhiều năm trước, chúng tôi sẽ bắt đầu với một mô tả tiếng Anh đơn giản về hệ thống mà khách hàng cần.

Nhìn qua đó, bất kỳ danh từ (hoặc cụm danh từ) sẽ được coi là một lớp có thể. Bất kỳ động từ (hoặc cụm động từ) sẽ là phương thức tiềm năng trên các lớp. Vì vậy, "robot đóng bao" có thể là một lớp học BaggingRobot. "Mở túi" có thể trở thành phương pháp OpenBag.

Sau một vài lần lặp lại, điều này sẽ biến thành một sơ đồ lớp.

Tại thời điểm này, không có lớp trừu tượng. Khách hàng không muốn có một khái niệm trừu tượng về robot đóng bao. Họ muốn một con robot đặt đồ vào túi. Tất cả các lớp là cụ thể và có một bộ phương pháp.

Các lớp trừu tượng chỉ được giới thiệu khi nó trở nên rõ ràng rằng:

  • Có một số lớp tương tự có thể tạo thành một hệ thống phân cấp.
  • Họ thực sự chia sẻ một cái gì đó chung, để một lớp cơ sở thực hiện một mục đích hữu ích.

Đối với tôi, "sự trừu tượng sớm" là giả định rằng bất kỳ ai BaggingRobot cũng phải thừa hưởng từ một số người BaseRobot, và tệ hơn nữa là cố gắng phát triển một tập hợp các phương pháp BaseRobottrước khi bạn biết những gì là phổ biến đối với tất cả các robot.


Trừu tượng không đồng nghĩa với các lớp trừu tượng. Một giao diện là một sự trừu tượng. Tôi đang nói về trừu tượng nói chung, không chỉ các lớp trừu tượng. Có lẽ tôi có thể làm cho điều này rõ ràng hơn bằng cách sử dụng một giao diện. Nếu bạn phát triển hệ thống của mình trên cùng một lớp trừu tượng với máy khách thì có khả năng bạn sẽ kết thúc với một số lớp trừu tượng cần được mở rộng vì ngôn ngữ là trừu tượng tự nhiên. Làm việc thấp hơn đó là cái mà tôi gọi là "sự lắng đọng sớm" nơi bạn ngây thơ cho rằng các ý tưởng của khách hàng về cách hệ thống sẽ hoạt động, giống như của bạn.
James

Một đối tượng BaggingRobot đặt các đối tượng Item vào các đối tượng Bag đã là một sự trừu tượng của một robot đóng bao thực sự đặt mọi thứ vào trong túi.
dùng253751

1

Nghe có vẻ giống như bạn muốn giải quyết vấn đề chưa tồn tại và bạn không có lý do chính đáng nào để cho rằng sẽ xảy ra, trừ khi bạn tin rằng khách hàng đã sai trong những gì họ yêu cầu. Nếu đó là trường hợp, tôi sẽ khuyên bạn nên giao tiếp nhiều hơn bằng cách thực hiện một giải pháp đoán, trừu tượng hoặc cách khác. Mặc dù có vẻ vô hại khi chỉ tát "trừu tượng" vào định nghĩa lớp và cảm thấy an toàn khi biết bạn có thể mở rộng nó sau này, bạn có thể thấy rằng bạn không bao giờ cần, hoặc bạn có thể thấy mình mở rộng nó theo cách làm phức tạp hóa thiết kế xuống dòng, bằng cách trừu tượng hóa những điều sai.

Đi với ví dụ của bạn, bạn có tưởng tượng rằng chính robot , các vật phẩm được đóng gói hoặc phương pháp đóng bao sẽ thay đổi dòng không?

Trừu tượng sớm thực sự chỉ có nghĩa là bạn không có lý do chính đáng để thực hiện trừu tượng hóa và vì trừu tượng là xa miễn phí trong nhiều ngôn ngữ, bạn có thể phải chịu chi phí mà không cần biện minh.

Chỉnh sửa Để trả lời một số điểm từ OP trong các bình luận, tôi đang cập nhật điều này để làm rõ và trả lời theo cách không yêu cầu chuỗi nhận xét dài trong khi giải quyết các điểm (1) và (2) cụ thể hơn.

(1) Đối với tôi điều này nghe có vẻ như lập trình viên không đủ thực dụng, họ đã đưa ra giả định rằng mọi thứ sẽ tồn tại trong chương trình cuối cùng không có , vì vậy họ đang làm việc với mức độ trừu tượng thấp, vấn đề không phải là trừu tượng sớm, đó là sự lắng đọng sớm.

(Nhấn mạnh mỏ). Giả sử mọi thứ sẽ tồn tại trong chương trình cuối cùng không chính xác như những gì tôi thấy trong ví dụ của bạn. Khách hàng yêu cầu một robot đóng gói vật phẩm. Đây là một yêu cầu rất cụ thể, nếu hơi mơ hồ trong ngôn ngữ của nó. Khách hàng muốn một robot có túi đồ, vì vậy bạn sản xuất một cặp đồ vật

public class Item {
/* Relevant item attributes as specified by customer */
}
public class BaggingRobot {
  private Collection<Item> items;

  public void bag(Item item);
}

Mô hình của bạn rất đơn giản và chính xác, nó tuân theo các yêu cầu do khách hàng đặt ra mà không cần thêm bất kỳ sự phức tạp nào vào giải pháp và không đưa ra giả định rằng khách hàng muốn nhiều hơn họ yêu cầu. Nếu, khi được trình bày với điều này, họ làm rõ nhu cầu robot có cơ chế đóng bao có thể hoán đổi cho nhau, chỉ khi đó bạn mới có đủ thông tin để biện minh cho việc tạo giao diện hoặc phương pháp trừu tượng khác, vì giờ đây bạn có thể chỉ ra giá trị cụ thể được thêm vào hệ thống thông qua sự trừu tượng.

Ngược lại, nếu bạn bắt đầu với sự trừu tượng hóa từ chủ nghĩa thực dụng thuần túy, bạn có thể dành thời gian để tạo một giao diện riêng và thực hiện nó một cách đơn giản, hoặc tạo một lớp trừu tượng, hoặc bất kỳ cách trừu tượng nào bạn thích. Nếu sau đó hóa ra khách hàng hài lòng với điều này và không cần gia hạn thêm nữa, bạn đã dành thời gian và nguồn lực vô ích, và / hoặc giới thiệu chi phí và sự phức tạp vào hệ thống mà không thu được lợi nhuận.

Liên quan đến (2), tôi đồng ý rằng việc bỏ qua những thứ quan trọng không phải là một dấu hiệu trừu tượng quá sớm. Trừu tượng hay không, bạn có thể bỏ qua một cái gì đó quan trọng và trừ khi nó được tìm thấy ở xa chuỗi trừu tượng, sẽ không khó hơn hoặc dễ dàng hơn để loại bỏ điều đó.

Thay vào đó , tôi sẽ giải thích rằng điều đó có nghĩa là bất kỳ sự trừu tượng hóa nào cũng có nguy cơ làm xáo trộn mô hình miền của bạn. Sự trừu tượng hóa không chính xác có thể làm cho một hệ thống trở nên rất khó để suy luận, vì bạn đang tạo ra các mối quan hệ có thể ảnh hưởng mạnh mẽ đến sự phát triển hơn nữa của mô hình miền và sự hiểu biết về tên miền. Bạn có nguy cơ bỏ sót thông tin không quan trọng về sự việc được trừu tượng hóa , nhưng về toàn bộ hệ thống , bằng cách đưa mô hình của bạn xuống lỗ thỏ sai.


"Nghe có vẻ giống như bạn muốn giải quyết vấn đề chưa tồn tại và bạn không có lý do chính đáng nào để cho rằng sẽ xảy ra, trừ khi bạn chỉ tin rằng khách hàng đã sai trong những gì họ yêu cầu." - Đây không phải là tất cả những gì tôi đã nói, trên thực tế tôi đã nói rõ rằng tôi chỉ xây dựng dựa trên những từ mà khách hàng sử dụng. Đó là hành động không muốn làm điều này đã thúc đẩy tôi sử dụng sự trừu tượng.
Gia-cơ

"Tôi muốn giới thiệu nhiều giao tiếp hơn khi thực hiện giải pháp đoán" - Ý bạn là như tôi đã đề xuất? Để trích dẫn những gì tôi đã nói trong OP "giải pháp cho vấn đề này không phải là đưa ra sự lãng phí và lãng phí tài nguyên của riêng bạn khi bạn phát hiện ra mình đoán sai, đó là để có thêm thông tin từ khách hàng."
Gia-cơ

"Mặc dù có vẻ vô hại khi chỉ tát 'trừu tượng' vào định nghĩa lớp và cảm thấy an toàn khi biết bạn có thể mở rộng nó sau này" - Khi tôi nói "trừu tượng", tôi có nghĩa là "trừu tượng" Tôi không có nghĩa là "từ khóa trừu tượng". Các giao diện có thể là trừu tượng, trừu tượng là logic mờ, đó là những gì toàn bộ bài viết này đang nói về. Khách hàng đang giao tiếp dưới dạng trừu tượng, vì vậy chúng ta nên lập trình theo thuật ngữ trừu tượng cho đến khi chúng ta biết thêm về tên miền.
Gia-cơ

1
"Bạn có thể thấy rằng bạn không bao giờ cần phải" - Điều này không có ý nghĩa gì. Một khách hàng nói "Tôi muốn một robot có túi đồ", bạn tạo ra một sự trừu tượng đáp ứng các tiêu chí đó. Bất kỳ thông tin nào khác bạn nhận được từ khách hàng sẽ là thông tin chi tiết về cách họ muốn thực hiện việc đóng bao. Điều này không làm mất hiệu lực sự trừu tượng của bạn, khách hàng không đột nhiên thay đổi suy nghĩ của họ về một ý tưởng cốt lõi đằng sau những gì họ đang mua. Các robot vẫn sẽ đi túi đồ. Sự trừu tượng mà bạn tạo ra vẫn sẽ được áp dụng.
Gia-cơ

"Hoặc bạn có thể thấy mình mở rộng nó theo cách làm phức tạp hóa thiết kế xuống dòng, bằng cách trừu tượng hóa những điều sai trái." ... Bạn đã thành thật đọc những gì tôi nói hay chỉ là tiêu đề? Nghiêm túc? Đọc điểm (1) & (2)
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.