Nhưng không phải phương thức draw () phụ thuộc rất nhiều vào giao diện người dùng là gì?
Từ một kiểu xem thực dụng, một số mã trong hệ thống của bạn cần biết cách vẽ một cái gì đó giống như Rectangle
nếu đó là yêu cầu cuối của người dùng. Và điều đó sẽ sôi sục vào một lúc nào đó để làm những việc thực sự ở mức độ thấp như raster pixel hoặc hiển thị một cái gì đó trong bảng điều khiển.
Câu hỏi cho tôi từ quan điểm khớp nối là ai / cái gì nên phụ thuộc vào loại thông tin này, và mức độ chi tiết nào (như thế nào trừu tượng, ví dụ)?
Tóm tắt khả năng vẽ / kết xuất
Bởi vì nếu mã bản vẽ cấp cao hơn chỉ phụ thuộc vào thứ gì đó rất trừu tượng, thì sự trừu tượng đó có thể có thể hoạt động (thông qua việc thay thế các triển khai cụ thể) trên tất cả các nền tảng bạn định nhắm mục tiêu. Như một ví dụ giả định, một số IDrawer
giao diện rất trừu tượng có thể có khả năng được triển khai trong cả API giao diện điều khiển và GUI để làm những việc như hình dạng cốt truyện (việc triển khai giao diện điều khiển có thể coi giao diện điều khiển như một "hình ảnh" 80xN với nghệ thuật ASCII). Tất nhiên đó là một ví dụ giả định vì đó thường không phải là điều bạn muốn làm là coi đầu ra của giao diện điều khiển như bộ đệm hình ảnh / khung; thông thường hầu hết các nhu cầu cuối của người dùng đều yêu cầu nhiều tương tác dựa trên văn bản hơn trong bảng điều khiển.
Một xem xét khác là làm thế nào dễ dàng để thiết kế một trừu tượng ổn định? Bởi vì có thể dễ dàng nếu tất cả những gì bạn nhắm đến là các API GUI hiện đại để trừu tượng hóa các khả năng vẽ hình cơ bản như vẽ đường thẳng, hình chữ nhật, đường dẫn, văn bản, những thứ thuộc loại này (chỉ đơn giản là rasterization 2D một bộ nguyên thủy hạn chế) , với một giao diện trừu tượng có thể dễ dàng thực hiện cho tất cả chúng thông qua các kiểu con khác nhau với ít chi phí. Nếu bạn có thể thiết kế một cách trừu tượng như vậy một cách hiệu quả và thực hiện nó trên tất cả các nền tảng đích, thì tôi sẽ nói rằng đó là một điều xấu xa hơn nhiều, thậm chí là một điều ác, đối với một hình dạng hoặc điều khiển GUI hoặc bất cứ điều gì biết cách tự vẽ bằng cách sử dụng một trừu tượng hóa.
Nhưng giả sử bạn đang cố gắng trừu tượng hóa các chi tiết khác nhau giữa Playstation Portable, iPhone, XBox One và PC chơi game mạnh mẽ trong khi nhu cầu của bạn là sử dụng các kỹ thuật kết xuất / tạo bóng 3D thời gian thực tiên tiến nhất trên mỗi thiết bị . Trong trường hợp đó, cố gắng đưa ra một giao diện trừu tượng để trừu tượng hóa các chi tiết kết xuất khi các khả năng và API phần cứng cơ bản khác nhau đến mức gần như chắc chắn sẽ dẫn đến việc thiết kế và thiết kế lại rất nhiều thời gian, xác suất cao của thiết kế định kỳ thay đổi với không lường trước được những khám phá và tương tự là một giải pháp mẫu số chung thấp nhất không khai thác được toàn bộ tính duy nhất và sức mạnh của phần cứng cơ bản.
Làm cho dòng chảy phụ thuộc theo hướng ổn định, thiết kế "dễ dàng"
Trong lĩnh vực của tôi, tôi đang ở trong kịch bản cuối cùng đó. Chúng tôi nhắm mục tiêu rất nhiều phần cứng khác nhau với các khả năng và API cơ bản hoàn toàn khác nhau và cố gắng đưa ra một bản tóm tắt vẽ / vẽ để thống trị tất cả là vô vọng (chúng tôi có thể trở nên nổi tiếng thế giới khi làm điều đó một cách hiệu quả vì nó sẽ là một trò chơi người thay đổi trong ngành). Vì vậy, điều cuối cùng tôi muốn trong trường hợp của tôi là như analogical Shape
hay Model
hay Particle Emitter
mà biết làm thế nào để vẽ bản thân, ngay cả khi nó được bày tỏ rằng bản vẽ trong cấp cao nhất và cách mà hầu hết trừu tượng có thể ...
... bởi vì những trừu tượng đó quá khó để thiết kế chính xác và khi một thiết kế khó có thể chính xác, và mọi thứ phụ thuộc vào nó, đó là một công thức cho những thay đổi thiết kế trung tâm tốn kém nhất mà gợn và phá vỡ mọi thứ tùy thuộc vào nó. Vì vậy, điều cuối cùng bạn muốn là cho các phụ thuộc trong hệ thống của bạn chuyển sang các thiết kế trừu tượng quá khó để có được chính xác (quá khó để ổn định mà không có thay đổi xâm nhập).
Khó phụ thuộc vào dễ, không dễ phụ thuộc vào khó
Vì vậy, những gì chúng tôi làm thay vì làm cho các phụ thuộc chảy vào những thứ dễ thiết kế. Thật dễ dàng hơn nhiều để thiết kế một "Mô hình" trừu tượng, chỉ tập trung vào việc lưu trữ những thứ như đa giác và vật liệu và làm cho thiết kế đó chính xác hơn là thiết kế một "Trình kết xuất" trừu tượng có thể được thực hiện một cách hiệu quả (thông qua các kiểu con bê tông thay thế) cho bản vẽ dịch vụ yêu cầu thống nhất cho phần cứng khác nhau như PSP từ PC.
Vì vậy, chúng tôi đảo ngược sự phụ thuộc ra khỏi những thứ khó thiết kế. Thay vì làm cho các mô hình trừu tượng biết cách tự vẽ một thiết kế kết xuất trừu tượng mà tất cả chúng phụ thuộc vào (và phá vỡ các triển khai của chúng nếu thiết kế đó thay đổi), thay vào đó chúng ta có một trình kết xuất trừu tượng biết cách vẽ mọi đối tượng trừu tượng trong cảnh của chúng ta ( các mô hình, trình phát hạt, v.v.) và do đó chúng ta có thể triển khai một kiểu con trình kết xuất OpenGL cho PC như RendererGl
, một kiểu khác cho PSP như RendererPsp
, một kiểu khác cho điện thoại di động, v.v. Trong trường hợp đó, các phụ thuộc đang chuyển sang các thiết kế ổn định, dễ dàng để có được chính xác, từ trình kết xuất đến các loại thực thể khác nhau (mô hình, hạt, kết cấu, v.v.) trong cảnh của chúng tôi, không phải theo cách khác.
- Tôi đang sử dụng "tính ổn định / không ổn định" theo nghĩa hơi khác so với chỉ số khớp nối liên kết / hiệu quả của chú Bob đang đo lường nhiều khó khăn của sự thay đổi theo như tôi có thể hiểu. Tôi đang nói nhiều hơn về "xác suất yêu cầu thay đổi", mặc dù chỉ số ổn định của anh ta rất hữu ích ở đó. Khi "xác suất thay đổi" tỷ lệ thuận với "dễ thay đổi" (ví dụ: những thứ có khả năng yêu cầu thay đổi có độ khớp cao nhất và không ổn định từ số liệu của chú Bob), thì mọi thay đổi có thể xảy ra như vậy đều rẻ và không xâm phạm , chỉ yêu cầu thay thế một triển khai mà không chạm vào bất kỳ thiết kế trung tâm.
Nếu bạn thấy mình đang cố gắng trừu tượng hóa một thứ gì đó ở cấp độ trung tâm của cơ sở mã của mình và nó quá khó để thiết kế, thay vì đập đầu một cách bướng bỉnh vào tường và liên tục thực hiện các thay đổi xâm phạm mỗi tháng / năm yêu cầu cập nhật 8.000 tệp nguồn vì nó phá vỡ mọi thứ phụ thuộc vào nó, đề nghị số một của tôi là xem xét đảo ngược các phụ thuộc. Xem bạn có thể viết mã theo cách khó thiết kế hay không phụ thuộc vào mọi thứ khác dễ thiết kế hơn, không có những thứ dễ thiết kế hơn tùy thuộc vào thứ rất khó thiết kế. Lưu ý rằng tôi đang nói về thiết kế (cụ thể là thiết kế giao diện) chứ không phải triển khai: đôi khi mọi thứ dễ thiết kế và khó thực hiện, và đôi khi mọi thứ khó thiết kế nhưng dễ thực hiện. Sự phụ thuộc chảy vào các thiết kế, vì vậy, trọng tâm chỉ nên tập trung vào mức độ khó của việc thiết kế ở đây để xác định hướng mà phụ thuộc chảy.
Nguyên tắc trách nhiệm duy nhất
Đối với tôi SRP không quá thú vị ở đây thường (mặc dù tùy thuộc vào ngữ cảnh). Ý tôi là có một hành động cân bằng chặt chẽ trong việc thiết kế những thứ rõ ràng có mục đích và có thể bảo trì được, nhưng Shape
đối tượng của bạn có thể phải tiết lộ thông tin chi tiết hơn nếu họ không biết cách tự vẽ, chẳng hạn, và có thể không có nhiều điều có ý nghĩa làm với một hình dạng trong một bối cảnh sử dụng cụ thể hơn là xây dựng nó và vẽ nó. Có sự đánh đổi với tất cả mọi thứ, và nó không liên quan đến SRP có thể khiến mọi thứ nhận thức được làm thế nào để bản thân có khả năng trở thành cơn ác mộng duy trì như vậy trong trải nghiệm của tôi trong những bối cảnh nhất định.
Nó có nhiều hơn để làm với khớp nối và hướng mà phụ thuộc chảy trong hệ thống của bạn. Nếu bạn đang cố gắng chuyển giao diện kết xuất trừu tượng mà mọi thứ phụ thuộc vào (vì họ đang sử dụng nó để tự vẽ) sang API / phần cứng mục tiêu mới và nhận ra rằng bạn phải thay đổi đáng kể thiết kế của nó để làm cho nó hoạt động hiệu quả ở đó, sau đó đó là một thay đổi rất tốn kém để thực hiện đòi hỏi phải thay thế việc triển khai mọi thứ trong hệ thống của bạn để biết cách tự vẽ. Và đó là vấn đề bảo trì thiết thực nhất mà tôi gặp phải với những điều nhận thức về cách tự vẽ nếu điều đó chuyển thành một khối lượng phụ thuộc chảy vào trừu tượng, quá khó để thiết kế chính xác.
Niềm tự hào của nhà phát triển
Tôi đề cập đến một điểm này bởi vì, theo kinh nghiệm của tôi, đây thường là trở ngại lớn nhất để chuyển hướng phụ thuộc vào những thứ dễ thiết kế hơn. Rất dễ dàng để các nhà phát triển có một chút tham vọng ở đây và nói: "Tôi sẽ thiết kế sự trừu tượng hóa kết xuất đa nền tảng để cai trị tất cả, tôi sẽ giải quyết những gì các nhà phát triển khác dành hàng tháng để chuyển và tôi sẽ nhận được đúng và nó sẽ hoạt động như ma thuật trên mọi nền tảng mà chúng tôi hỗ trợ và sử dụng các kỹ thuật kết xuất hiện đại trên mọi nền tảng; tôi đã hình dung ra nó trong đầu. "Trong trường hợp họ chống lại giải pháp thực tế đó là tránh làm điều đó và chỉ cần lật hướng phụ thuộc và dịch những gì có thể rất tốn kém và thay đổi thiết kế trung tâm thành những thay đổi định kỳ đơn giản và rẻ tiền để thực hiện. Cần phải có một bản năng "cờ trắng" nào đó trong các nhà phát triển để từ bỏ khi một thứ gì đó quá khó để thiết kế đến mức trừu tượng như vậy và xem xét lại toàn bộ chiến lược của họ, nếu không họ sẽ rất đau buồn và đau đớn. Tôi sẽ đề nghị chuyển những tham vọng và tinh thần chiến đấu như vậy sang các triển khai hiện đại của một thứ dễ dàng hơn để thiết kế hơn là đưa tham vọng chinh phục thế giới này đến mức thiết kế giao diện.