Nhiều lớp có cùng tên, nhưng không gian tên khác nhau?


11

Tôi đã chạy vào một số mã (C # nếu có vấn đề) có các lớp có cùng tên, nhưng khác nhau về không gian tên của chúng. Tất cả đều có xu hướng đại diện cho cùng một điều logic, nhưng thường là "quan điểm" khác nhau của cùng một đối tượng. Các không gian tên khác nhau đôi khi là một phần của cùng một giải pháp và thậm chí là cùng một dll.

Tôi có suy nghĩ của mình, nhưng không thể tìm thấy bất cứ điều gì dứt khoát về thực hành này để được coi là sử dụng thông minh các công cụ có sẵn hoặc một mô hình để tránh.

Câu hỏi này về đặt tên smurf chạm vào điều này, nhưng từ hướng khác. Việc định nghĩa các tên có thể sẽ yêu cầu một tiền tố tùy ý và phổ biến, mà câu hỏi đó muốn loại bỏ.

Các hướng dẫn xung quanh thực hành này là gì?


1
Trong OOP có nhiều trường hợp ngoại lệ, nhưng lúc đầu tôi xem xét thiết kế tồi này, đặc biệt nếu tất cả các lớp có chung mức độ truy cập. Khi tôi đọc một tên lớp, trong bất kỳ tệp nào, sau đó tôi muốn biết trong không gian tên nào lớp được đặt ngay lập tức mà không phải tham khảo các chỉ thị không gian tên.
Leopold Asperger

Có một trường hợp hợp lệ để có nhiều đối tượng liên quan xử lý cùng một trạng thái, nhưng thông thường chúng được phân tách bằng chức năng. Có thể bạn có một đối tượng điều chỉnh mô hình để xem. Một số khác có thể thực hiện một phép tính trên đối tượng. Một cái khác có thể là một bộ chuyển đổi hoặc mặt tiền. Vì vậy, bạn có thể có FooAdapter, FooViewer, FooCalculator, vv nhưng chắc chắn không có tên giống nhau. Tuy nhiên, nếu không có thêm thông tin về các lớp cụ thể mà bạn đang nói, thật khó để đưa ra câu trả lời.

@JohnGaughan - xem xét Employeelàm ví dụ. Có một nhân viên dành cho các nhân viên khác, một cho nhân sự, một cho tiếp xúc bên ngoài. Tất cả họ đều được đặt tên là "nhân viên" và tất cả họ đều có nhiều người giúp đỡ (EmployeeRep repository, EmployeeView, v.v.). Tất cả đều ở trong cùng một dll và trong khi họ chia sẻ một số thuộc tính chung (tên, tiêu đề), tất cả đều khác nhau (số điện thoại, tiền lương).
Telastyn

Đã làm việc với các hệ thống mô hình Employeenhiều lần, có vẻ như bạn cần một mô hình với sự kết hợp của tất cả các thuộc tính và bao gồm một typehoặc departmentthuộc tính. Mặt khác, không cần sao chép mã.

5
Đây không phải là một trong những lý do cho không gian tên bắt đầu sao? Để cho phép va chạm tên?
Dan Pichelman

Câu trả lời:


5

Tôi sẽ cố gắng đưa ra câu trả lời chống lại việc sử dụng đó, sau khi đã thấy và làm việc này trong một trong các dự án của tôi.

Mã dễ đọc

Trước hết, hãy xem xét rằng khả năng đọc mã là quan trọng và thực tế này là đối trọng với điều đó. Ai đó đọc một đoạn mã và hãy nói rằng nó có chức năng doSomething(Employee e). Điều này không còn có thể đọc được nữa, do có 10 Employeelớp khác nhau tồn tại trong các gói khác nhau, trước tiên bạn sẽ phải sử dụng khai báo nhập khẩu để tìm hiểu xem đầu vào của bạn thực sự là gì.

Tuy nhiên, đây là chế độ xem cấp cao và chúng tôi thường có các xung đột tên dường như ngẫu nhiên, không ai quan tâm hoặc thậm chí không tìm thấy, vì ý nghĩa có thể được lấy từ mã còn lại và gói bạn đang ở. Vì vậy, người ta thậm chí có thể tranh luận rằng, tại địa phương, không có vấn đề gì, vì tất nhiên nếu bạn thấy Employeetrong một hrgói bạn phải biết rằng chúng ta đang nói về quan điểm nhân sự của nhân viên.

Mọi thứ tan vỡ ngay khi bạn rời khỏi các gói này mặc dù. Khi bạn đang làm việc trong một mô-đun / gói / vv khác nhau và cần phải làm việc với một nhân viên, bạn đã hy sinh khả năng đọc nếu bạn không đủ điều kiện loại của nó. Ngoài ra, có 10 Employeelớp khác nhau có nghĩa là tự động hoàn thành IDE của bạn sẽ không còn hoạt động nữa và bạn phải chọn thủ công từ loại nhân viên.

Sao chép mã

Do bản chất của mỗi lớp này có liên quan với nhau, mã của bạn bị ràng buộc xấu đi do có nhiều sự trùng lặp. Trong hầu hết các trường hợp, bạn sẽ có một cái gì đó giống như tên của nhân viên hoặc một số số nhận dạng, mà mỗi lớp phải thực hiện. Mặc dù mỗi lớp thêm loại quan điểm riêng của mình, nếu họ không chia sẻ dữ liệu nhân viên cơ bản, thì bạn sẽ kết thúc với một khối lượng lớn mã vô dụng, nhưng tốn kém.

Độ phức tạp của mã

Điều gì có thể phức tạp như vậy bạn có thể yêu cầu? Rốt cuộc, mỗi lớp có thể giữ nó đơn giản như nó muốn. Điều thực sự trở thành một vấn đề là cách bạn tuyên truyền những thay đổi. Trong một phần mềm giàu tính năng hợp lý, bạn có thể thay đổi dữ liệu nhân viên - và bạn muốn phản ánh điều đó ở mọi nơi. Nói rằng một người phụ nữ vừa mới kết hôn và bạn phải đổi tên của mình từ XđếnYvì điều đó. Đủ khó để làm điều này đúng ở mọi nơi, nhưng thậm chí còn khó hơn khi bạn có tất cả các lớp riêng biệt này. Tùy thuộc vào các lựa chọn thiết kế khác của bạn, điều này có thể dễ dàng có nghĩa là mỗi lớp phải thực hiện loại trình nghe riêng của mình hoặc được thông báo về các thay đổi - về cơ bản chuyển thành một yếu tố được áp dụng cho số lượng lớp bạn phải xử lý . Tất nhiên, nhiều mã sao chép mã hơn và khả năng đọc mã ít hơn, .. Các yếu tố như thế này có thể bị bỏ qua trong phân tích độ phức tạp, nhưng chúng chắc chắn gây khó chịu khi áp dụng cho kích thước cơ sở mã của bạn.

Mã giao tiếp

Ngoài các vấn đề về độ phức tạp mã ở trên, cũng liên quan đến lựa chọn thiết kế, bạn cũng đang giảm độ rõ ràng của thiết kế cấp cao hơn và mất khả năng giao tiếp đúng với các chuyên gia tên miền. Khi bạn thảo luận về kiến ​​trúc, thiết kế hoặc yêu cầu, bạn không còn tự do đưa ra những tuyên bố đơn giản như thế nào given an employee, you can do .... Một nhà phát triển sẽ không còn biết những gì employeethực sự có nghĩa là tại thời điểm đó. Mặc dù một chuyên gia tên miền sẽ biết điều đó tất nhiên. Tất cả chúng ta làm. loại. Nhưng về phần mềm thì không dễ để giao tiếp nữa.

Làm thế nào để thoát khỏi vấn đề

Sau khi nhận thức được điều này và nếu nhóm của bạn đồng ý rằng đó là một vấn đề đủ lớn để giải quyết, thì bạn sẽ phải tìm ra cách giải quyết. Thông thường, bạn không thể yêu cầu người quản lý của mình cho cả đội nghỉ một tuần để họ có thể bỏ rác. Vì vậy, về bản chất, bạn sẽ phải tìm cách loại bỏ một phần các lớp này, từng lớp một. Phần quan trọng nhất về vấn đề này là quyết định - với toàn đội - Employeethực sự là gì. Đừng không tích hợp tất cả các thuộc tính cá nhân thành một vị thần-nhân viên. Hãy suy nghĩ nhiều hơn về một nhân viên cốt lõi và quan trọng nhất là quyết định nơi Employeelớp học đó sẽ cư trú.

Nếu bạn thực hiện đánh giá mã, thì đặc biệt dễ dàng để đảm bảo rằng vấn đề ít nhất không phát triển thêm nữa, tức là dừng mọi người ngay trong bản nhạc của họ khi họ muốn thêm một Employeelần nữa. Cũng lưu ý rằng các hệ thống con mới tuân thủ thỏa thuận Employeevà không được phép truy cập các phiên bản cũ.

Tùy thuộc vào ngôn ngữ lập trình của bạn, bạn cũng có thể muốn đánh dấu các lớp cuối cùng sẽ bị loại bằng thứ gì đó như @Deprecatedđể hỗ trợ nhóm của bạn ngay lập tức nhận ra rằng họ đang làm việc với thứ gì đó sẽ phải thay đổi.

Đối với việc loại bỏ các lớp nhân viên lỗi thời, bạn có thể quyết định cho từng trường hợp riêng biệt về cách loại bỏ tốt nhất hoặc chỉ đồng ý về một mô hình chung. Bạn có thể gắn tên lớp và bọc nó xung quanh nhân viên thực sự, bạn có thể sử dụng các mẫu (trang trí hoặc bộ điều hợp đến trong tâm trí), hoặc, hoặc.

Nói một cách ngắn gọn: "Thực hành" này nghe có vẻ kỹ thuật, nhưng bị bóp nghẹt với đầy đủ các chi phí tiềm ẩn sẽ chỉ xảy ra ở phía dưới. Mặc dù bạn có thể không thể thoát khỏi vấn đề ngay lập tức, nhưng bạn có thể bắt đầu ngay lập tức với việc chứa các tác động có hại của nó.


Có một lớp Core có vẻ như là một giải pháp tốt. Các lớp khác có thể mở rộng từ nó. Về IDE, hoàn thành tự động đủ thông minh để biết lớp nào sẽ gợi ý cho bạn để phù hợp nhất với bối cảnh. Nhìn chung, tôi không hiểu tại sao đây lại là một vấn đề lớn như vậy đặc biệt là nếu codebase được sử dụng nội bộ.
Được thông báo vào

1
Nó không đủ thông minh một khi bạn ở ngoài một bối cảnh. Hãy xem xét một lớp, thực sự cần cả hai lớp có vấn đề - tự động hoàn thành sẽ không giúp ích gì cả. Và nó thậm chí sẽ không phân biệt chúng với mười lớp khác. Nhưng vấn đề thực sự là thành viên nhóm mới, người thậm chí không biết tất cả các tên miền gói đó thực sự là gì và anh ta nên chọn cái nào.
Frank

Nếu nhiều lớp có cùng tên đang được sử dụng trong cùng một ngữ cảnh, thì thật khó. Tôi chưa thấy trường hợp đó. Tôi đã thấy nhiều lớp có cùng tên, nhưng chúng không thường được sử dụng trong cùng bối cảnh như bạn đã đề cập.
Được thông báo vào

@randomA - thật đáng buồn, trường hợp đó khá phổ biến trong cơ sở mã này.
Telastyn

Điểm hay, nhưng bạn chưa thực sự đưa ra giải pháp cho vấn đề cốt lõi, chỉ có phương pháp một khi vấn đề cốt lõi được giải quyết ("nhân viên thực sự là gì"). "Giải pháp" rõ ràng duy nhất ("tích hợp tất cả các thuộc tính riêng lẻ vào một nhân viên thần") mà bạn đã loại bỏ, đúng như vậy. Giả sử bạn có DB.Employee, Marshalling.Employee, ViewModels.Employee, GUI.Views.Employee, v.v., giải pháp của bạn là gì?
Pablo H

8

Khung sưu tập Scala là một ví dụ tốt về điều này. Có các bộ sưu tập có thể thay đổi và bất biến cũng như các bộ sưu tập nối tiếp và song song (và trong tương lai cũng có thể được phân phối). Vì vậy, có, ví dụ, bốn Mapđặc điểm:

scala.collection.Map
scala.collection.immutable.Map
scala.collection.mutable.Map
scala.collection.concurrent.Map

cộng ba ParMaps:

scala.collecion.parallel.ParMap
scala.collecion.parallel.immutable.ParMap
scala.collecion.parallel.mutable.ParMap

Thậm chí thú vị hơn:

scala.collection.immutable.Map            extends scala.collection.Map
scala.collection.mutable.Map              extends scala.collection.Map
scala.collection.concurrent.Map           extends scala.collection.mutable.Map

scala.collecion.parallel.ParMap           extends scala.collection.Map
scala.collecion.parallel.immutable.ParMap extends scala.collecion.parallel.ParMap
scala.collecion.parallel.mutable.ParMap   extends scala.collecion.parallel.ParMap

Vì vậy, ParMapmở rộng kéo ParMapdài MapMapmở Maprộng kéo dài Map.

Nhưng, hãy đối mặt với nó: bạn sẽ gọi họ là gì khác? Điều này làm cho ý nghĩa hoàn hảo. Đó là không gian tên dành cho!


3
"Đó là không gian tên dành cho!" => +1
svidgen

Tôi thích điều này, nhưng trong thế giới C # /. NET khi tôi chuyển các lớp song song sang không gian tên phụ song song, sau đó đụng độ với lớp trợ giúp System.Threading.Parallel, mà tôi tình cờ sử dụng nhiều để có được sự song song. Tôi không muốn sử dụng không gian tên 'Đồng thời' thay vào đó vì nó đã được sử dụng để có nghĩa là 'truy cập đồng thời' trên các lớp bộ sưu tập. Như một sự thỏa hiệp tôi đã chọn cho không gian tên phụ 'Song song'.
redcalx

2

Đây là một câu hỏi thực sự thú vị trong đó hai câu trả lời cơ bản đối lập đều đúng. Đây là một ví dụ thực tế về cuộc thảo luận này mà chúng tôi đang có trong một dự án của tôi.

Tôi nghĩ rằng có hai cân nhắc rất nổi bật cho đến nay sẽ khiến bạn muốn đi theo hướng này hay hướng khác, rút ​​ra từ hai câu trả lời từ @Jorg và @Frank:

  1. Nếu bạn dự đoán một tình huống có thể cần sử dụng nhiều hơn một trong các lớp cùng tên trong cùng một bối cảnh mã, thì đây là lý do không sử dụng cùng tên. Đó là, nếu bạn cần phải làm việc với hr.Employeenhưng đồng thời cần xem xét các quyền thông qua security.Employee, điều đó sẽ gây khó chịu rất nhanh.
  2. Ngược lại, nếu các lớp của bạn có cùng tên đều có API giống nhau hoặc rất giống nhau, thì đó là một ví dụ điển hình về việc khi nào bạn nên sử dụng cùng tên với các không gian tên khác nhau. Ví dụ Scala chính xác là thế này, trong đó tất cả các Maplớp thực hiện cùng một giao diện hoặc là các lớp con của nhau. Trong trường hợp này, sự mơ hồ hoặc "nhầm lẫn" có thể được gọi là một điều tốt, bởi vì người dùng có thể đối xử đúng với tất cả các triển khai của lớp hoặc giao diện giống nhau ... đó là điểm của giao diện và các lớp con.
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.