Điều gì nếu toàn cầu có ý nghĩa?


10

Tôi đã có một giá trị mà nhiều đối tượng cần. Ví dụ, một ứng dụng tài chính với các khoản đầu tư khác nhau làm đối tượng và hầu hết trong số chúng cần lãi suất hiện tại.

Tôi đã hy vọng gói gọn "môi trường tài chính" của mình như một đối tượng, với lãi suất như một tài sản. Nhưng, anh chị em đối tượng cần giá trị đó không thể có được nó.

Vậy làm cách nào để chia sẻ giá trị giữa nhiều đối tượng mà không khớp nối thiết kế của tôi? Rõ ràng là tôi đang nghĩ về điều này sai.


2
Là lãi suất cố định trong suốt thời gian tính toán của bạn hay bạn đang làm một cái gì đó giống như một mô phỏng nơi nó có thể thay đổi giữa các dấu thời gian?
James

Nó giống như một mô phỏng - nó có thể thay đổi trong quá trình chạy.
Greg

Trong trường hợp đó, mỗi khoản đầu tư có thực sự cần phải tiết kiệm lãi suất hay có thể nhận khoản đầu tư đó thông qua một tham số cho một updatechức năng được gọi tại mỗi dấu thời gian không? Bạn có thể đăng trong mã giả cách mô phỏng của bạn hoạt động?
James

3
Bạn là một trong những ca khúc chính xác, a Singletonlà một toàn cầu với đường cú pháp OO trên đó và là một giải pháp khủng khiếp kết hợp chặt chẽ mã của bạn theo một số cách tồi tệ nhất có thể. Đọc bài viết này nhiều lần cho đến khi bạn hiểu nó!

Lãi suất giống như một chuỗi thời gian là một hàm lấy DateTimeđầu vào và trả về một số làm đầu ra.
rwong

Câu trả lời:


14

Tôi đã có một giá trị mà nhiều đối tượng cần.

Đây là một mùi thiết kế. Không có gì lạ khi nhiều đối tượng cần biết về điều gì đó. Điều đó nói rằng, lãi suất hiện tại là một ví dụ khá tốt về các trường hợp đặc biệt. Một điều cần lo lắng về là có hiếm khi các lãi suất. Các công cụ tài chính khác nhau sử dụng tỷ lệ khác nhau. Ít nhất, các địa phương khác nhau sử dụng tỷ lệ 'tiêu chuẩn' khác nhau. Hơn nữa, để hỗ trợ kiểm tra và báo cáo, bạn thường muốn vượt qua một tỷ lệ vì bạn không muốn sử dụng tỷ lệ hiện tại ở đó. Bạn muốn sử dụng tỷ lệ 'what if' hoặc 'kể từ ngày báo cáo'.

Vậy làm cách nào để chia sẻ giá trị giữa nhiều đối tượng mà không khớp nối thiết kế của tôi?

Bằng cách chia sẻ chúng, không có tất cả chúng đề cập đến một trường hợp duy nhất. Vượt qua điều tương tự xung quanh vẫn là khớp nối ở một mức độ, nhưng không vượt quá khớp nối vì một số thứ như lãi suất hiện tại là cần thiết để nhập vào một loạt các tính toán.


17
Vấn đề với các trường hợp đặc biệt là trong phần mềm thế giới thực, chúng không phải là ngoại lệ.
mattnz

Tôi nghĩ rằng đây là một sự hiểu lầm nghiêm trọng. Các thuật toán của chúng tôi tồn tại trong các bối cảnh khác nhau cùng một lúc. Đầu tiên là bối cảnh toàn cầu. Sau đó, "bối cảnh" này cho các ngôn ngữ hướng đối tượng. Bối cảnh phiên trong dịch vụ web, bối cảnh giao dịch trong môi trường DB, Cửa sổ chính cho gui, ... và có những thông tin thuộc về các bối cảnh này. Họ phải "quanh quẩn" và có sẵn, cùng một bộ (đối tượng) cho bất kỳ ai trong cùng bối cảnh. Không sao đâu Vấn đề là giải quyết vấn đề này cho từng đối tượng, không phải bằng cách tạo một dịch vụ ngữ cảnh hoặc sử dụng một khung công tác, như Spring trong Java.
Lorand Kedves

3
Không có gì đặc biệt về lãi suất hiện tại. Có nhiều ví dụ về vật phẩm trong thế giới thực có một giá trị, - Giới hạn tốc độ đường mở, nồng độ cồn trong máu chấp nhận được, thuế suất thuế GST (hoặc VAT) để nêu tên rất ít. Đó là sự khác biệt giữa Khoa học và Kỹ thuật - Các kỹ sư giải quyết các vấn đề trong thế giới thực ngày nay, Các nhà khoa học mơ ước ngày thế giới thực sẽ phù hợp với những hộp hoàn hảo và giải quyết những vấn đề đó.
mattnz

1
Tôi chọn đây là câu trả lời vì nó đơn giản và không dựa vào một thập kỷ kinh nghiệm OOP để tìm kiếm. NHIỀU cảm ơn tất cả những người được hỏi. Tôi đã có một ngày để đọc nhờ nhiều tài liệu tham khảo nhưng vẫn còn một chút bối rối. Đối với một câu hỏi đơn giản như vậy, tôi đã ngạc nhiên về sự đa dạng và cảm xúc đằng sau các câu trả lời. Tôi vẫn tin rằng đôi khi có một nguồn trung tâm của dữ liệu toàn cầu nhưng khác nhau được phục vụ tốt nhất bởi Singleton. Tôi không nghĩ người ta nên chuyển con trỏ lên và xuống một hệ thống phân cấp các đối tượng chỉ để tránh Singleton. Cảm ơn mọi người một lần nữa.
Greg

@mattnz, vấn đề là mỗi một ví dụ của bạn đều biến đổi trong trường hợp bạn phân phối chương trình của mình cho nhiều cơ sở người dùng có thể trải rộng các công ty, tiểu bang hoặc quốc gia. Tất cả chúng cũng có thể thay đổi theo thời gian.
Dan Lyons

10

Trong trường hợp cụ thể này, tôi sẽ sử dụng Mẫu Singleton . Môi trường tài chính sẽ là đối tượng mà tất cả các thư viện lớp khác đều biết, nhưng sẽ được Singleton khởi tạo. Lý tưởng nhất là bạn sẽ gửi đối tượng được khởi tạo đó đến các thư viện lớp khác nhau.

Ví dụ:

  • Lớp dịch vụ (thư viện lớp) - Khởi tạo đối tượng FinancialEn Môi trường thông qua một đơn vị
  • Lớp logic nghiệp vụ (thư viện lớp) - Chấp nhận đối tượng FinancialEn Môi trường từ lớp dịch vụ
  • Lớp truy cập dữ liệu (thư viện lớp) - Chấp nhận đối tượng FinancialEn Môi trường từ lớp dịch vụ (hoặc tùy thuộc vào kiến ​​trúc của bạn Lớp logic nghiệp vụ). Hoặc có thể Singleton gọi Lớp truy cập dữ liệu để lấy thông tin, chẳng hạn như lãi suất, từ kho lưu trữ (cơ sở dữ liệu / dịch vụ web / dịch vụ WCF).
  • Các thực thể (hoặc DTO nếu bạn muốn gọi nó là thư viện lớp) - Nơi đối tượng FinancialEn Môi trường sống. Tất cả các thư viện lớp khác có tham chiếu đến thư viện lớp Thực thể.

Các lớp khác chỉ được liên kết với nhau thông qua thư viện lớp Thực thể, chúng chấp nhận một đối tượng FinancialEn Môi trường tức thời. Họ không quan tâm làm thế nào nó được tạo ra, chỉ có lớp dịch vụ làm, tất cả những gì họ muốn là thông tin. Người độc thân cũng có thể đủ thông minh để lưu trữ một số đối tượng FinancialEn Môi trường, tùy thuộc vào các quy tắc cho địa phương như @Telastyn đã chỉ ra.

Bên cạnh đó, tôi không phải là một fan hâm mộ lớn của Mẫu Singleton, tôi coi đó là mùi mã, vì nó có thể bị lạm dụng rất dễ dàng. Nhưng trong một số trường hợp bạn cần nó.

Cập nhật:

Nếu bạn hoàn toàn, tích cực phải có một biến toàn cục thì việc triển khai Mô hình Singleton như mô tả ở trên sẽ hoạt động. Tuy nhiên, tôi không phải là một fan hâm mộ lớn của điều này, và dựa trên các bình luận từ bài viết gốc của tôi, một số người khác cũng không. Là một thứ gì đó không ổn định như InterestRate, Singleton có thể không phải là giải pháp tốt nhất. Singletons hoạt động tốt nhất khi thông tin không thay đổi. Ví dụ, tôi đã sử dụng Singleton trong một trong các ứng dụng của mình để khởi tạo bộ đếm hiệu suất. Bởi vì nếu chúng thay đổi thì bạn phải có logic để xử lý dữ liệu được cập nhật.

Nếu tôi là người cá cược, tôi sẽ đặt cược lãi suất được lưu trữ ở đâu đó trong cơ sở dữ liệu hoặc được lấy thông qua dịch vụ web. Trong trường hợp đó, Kho lưu trữ (lớp truy cập dữ liệu) sẽ được đề xuất để truy xuất thông tin đó. Để tránh các chuyến đi không cần thiết đến cơ sở dữ liệu (tôi không chắc mức độ thường xuyên thay đổi lãi suất hoặc thông tin khác trong lớp FinancialIn information), bộ nhớ đệm có thể được sử dụng. Trong thư viện Khối ứng dụng bộ đệm của Microsoft trên thế giới C # hoạt động rất tốt.

Điều duy nhất sẽ thay đổi so với ví dụ trên, sẽ là các lớp khác nhau trong lớp dịch vụ cần FinancialIn information sẽ truy xuất từ ​​Lớp truy cập dữ liệu thay vì Singleton khởi tạo đối tượng.


8
Ừ Làm cho toàn cầu trở thành một singleton không làm cho nó ít mùi hơn. Nếu bất cứ điều gì bạn đã giới hạn bản thân mình nhiều hơn nữa.
Telastyn

3
@DavidCowden không thành vấn đề nếu chúng không phức tạp để thực hiện; họ cho rằng thiết kế của bạn tệ hơn so với toàn cầu. Chúng là toàn cầu chúng thực thi các hạn chế (không cần thiết) mà bạn chỉ có một.
Telastyn

4
Tôi sẽ đăng một bình luận mỉa mai "làm cho nó trở thành một người độc thân và nó sẽ đi từ thực tiễn xấu đến thực tiễn tốt nhất", nhưng sau đó tôi thấy nó đã là một câu trả lời được chấp nhận và bỏ phiếu. Rất đẹp!
Kevin

4
Singletonlà một toàn cầu với đường cú pháp OO và một cái nạng cho những người lười biếng và suy nghĩ yếu đuối. Singleton/globallà cách tồi tệ nhất tuyệt đối để kết hợp chặt chẽ mã của bạn với thứ gì đó sẽ gây ung thư sau này khi bạn nhận ra ý tưởng tồi tệ đó là gì và tại sao mọi người nói chúng là!

4
@Telastyn: Một thực tế đáng tiếc là hầu hết các thiết kế hoàn hảo một khi họ rời khỏi thế giới thiết kế phần mềm lý thuyết được sắp xếp hoàn hảo và tham gia vào thế giới thực, nhận được fubar'd.
mattnz

4

Tập tin cấu hình?

Nếu bạn có các giá trị được sử dụng "toàn cầu", vui lòng đặt chúng vào tệp cấu hình. Sau đó, mỗi hệ thống và hệ thống con có thể tham chiếu điều này và kéo các phím cần thiết, làm cho chúng chỉ đọc.


Vì vậy, bạn sẽ có người dùng cập nhật một tệp cấu hình mỗi khi lãi suất thay đổi?
Caleb

2
Tại sao không? tất nhiên phụ thuộc vào "biến" tất nhiên những thứ thay đổi thường xuyên nên được đặt bên trong kho dữ liệu TRUNG TÂM.
Tối

1

Tôi đang nói về kinh nghiệm của một người có khoảng một tháng bảo trì cho một dự án có quy mô tốt (~ 50 nghìn LỘC) mà chúng tôi vừa phát hành.

Tôi có thể nói với bạn rằng bạn có thể không thực sự muốn một đối tượng toàn cầu. Giới thiệu loại tàu tuần dương này cung cấp nhiều cơ hội lạm dụng hơn là giúp ích.

Đề xuất ban đầu của tôi là nếu bạn có một vài lớp khác nhau cần lãi suất hiện tại thì có lẽ bạn muốn họ thực hiện một IInterestRateConsumerhoặc một cái gì đó. Trong giao diện đó, bạn sẽ có một SetCurrentInterestRate(double rate)(hoặc bất cứ điều gì có ý nghĩa), hoặc có thể chỉ là một tài sản.

Vượt qua một mức lãi suất không thực sự khớp - Nếu lớp của bạn cần lãi suất, đó là một phần của API. Nó chỉ khớp nếu một trong các lớp của bạn bắt đầu lo lắng về việc chính xác lớp kia sử dụng mức lãi suất đó như thế nào.


Vượt qua một mức lãi suất xung quanh khớp nối, nó không phải là khớp nối xấu .
vaughandroid

1

Martin Fowler có một bài viết nói ngắn gọn về cách tái cấu trúc toàn cầu tĩnh thành một thứ linh hoạt hơn. Về cơ bản, bạn biến nó thành một singleton sau đó sửa đổi singleton để nó hỗ trợ ghi đè lớp của cá thể bằng một lớp con (và nếu cần di chuyển logic tạo ra cá thể sang một lớp riêng biệt có thể được phân lớp, bạn sẽ làm gì nếu tạo ra siêu thể hiện thì việc thay thế nó sau này là một vấn đề).

Tất nhiên, bạn phải cân nhắc các vấn đề với singletons (thậm chí là singletons thay thế) so với nỗi đau khi vượt qua cùng một đối tượng ở khắp mọi nơi.

Theo như đối tượng "môi trường tài chính" - thật thuận tiện để lập trình trên đường chuyền đầu tiên, nhưng khi bạn hoàn thành, bạn đã thêm một số phụ thuộc bổ sung. Các lớp chỉ cần lãi suất bây giờ chỉ hoạt động khi thông qua một đối tượng môi trường tài chính, điều này sẽ khiến chúng khó sử dụng lại khi bạn không có đối tượng môi trường tài chính nói dối. Vì vậy, tôi sẽ không khuyến khích thông qua nó rộng rãi.


0

Tại sao không đặt dữ liệu lãi suất vào bộ đệm trung tâm?

Bạn có thể sử dụng một trong một số thư viện bộ đệm, tùy theo yêu cầu của bạn, điều gì đó như memcached sẽ giải quyết tất cả các vấn đề về quản lý mã và đồng thời của bạn và sẽ cho phép ứng dụng của bạn mở rộng theo nhiều quy trình.

Hoặc đi toàn bộ con lợn và lưu trữ chúng trong cơ sở dữ liệu, điều này sẽ cho phép bạn mở rộng quy mô đến nhiều máy chủ.


0

Trong các tình huống như vậy, tôi đã giới thiệu thành công (tái sử dụng) thuật ngữ "bối cảnh" với đôi khi nhiều lớp.

Điều này có nghĩa là một cửa hàng đối tượng "toàn cầu", do đó các loại đối tượng này có thể được yêu cầu. Các mã yêu cầu chúng, bao gồm tiêu đề của cửa hàng và sử dụng các hàm toàn cầu để lấy các thể hiện đối tượng của chúng (như bây giờ, nhà cung cấp lãi suất).

Cửa hàng có thể là:

  • được gõ đúng: bạn bao gồm các tiêu đề cho tất cả các loại được phục vụ và do đó bạn có thể tạo các bộ truy cập đã nhập, như InterestRate getCienInterestRate ();
  • hoặc chung chung: Object getObject (enum obType); và chỉ mở rộng enum obType với các loại mới (obtypeCienInterestRate).

Hệ thống càng lớn, giải pháp sau càng có thể sử dụng được, vì rủi ro khá nhỏ khi sử dụng enum sai. Mặt khác, với các ngôn ngữ cho phép khai báo kiểu chuyển tiếp, tôi nghĩ bạn có thể sử dụng các bộ truy cập được gõ mà không bao gồm tất cả các tiêu đề trong cửa hàng.

Thêm một lưu ý: bạn có thể có nhiều phiên bản của cùng một loại đối tượng cho các mục đích sử dụng khác nhau, như đôi khi giá trị Ngôn ngữ khác nhau cho GUI và cho bản in, nhật ký cấp toàn cầu và phiên, v.v., vì vậy tên enum / accessor KHÔNG nên phản ánh loại thực tế , nhưng vai trò của thể hiện được yêu cầu (CurrentInterestRate).

Trong triển khai cửa hàng, bạn phải quản lý các mức ngữ cảnh và các bộ sưu tập thể hiện ngữ cảnh. Một ví dụ đơn giản là dịch vụ web, nơi bạn có bối cảnh toàn cầu (một ví dụ cho tất cả các yêu cầu cho đối tượng đó - có vấn đề khi có cụm máy chủ) và bối cảnh cho mỗi phiên web. Bạn cũng có thể có bối cảnh cho từng người dùng, những người có thể có nhiều phiên song song, v.v. Với nhiều máy chủ, bạn nên sử dụng một loại bộ đệm được phân phối cho những thứ đó.

Khi yêu cầu đến, bạn quyết định mức ngữ cảnh của đối tượng được yêu cầu, lấy bối cảnh đó cho cuộc gọi. Nếu đối tượng ở đó, bạn gửi lại; nếu không, bạn tạo và lưu trữ nó ở mức ngữ cảnh đó và trả lại. Tất nhiên, đồng bộ hóa phần tạo (và xuất bản nó vào bộ đệm được phân phối). Việc tạo có thể giống như plugin có thể định cấu hình, tốt nhất với các ngôn ngữ cho phép tạo các thể hiện đối tượng theo tên lớp của chúng (Java, Objective C, ...), nhưng bạn cũng có thể làm điều đó trong C với các thư viện có thể cắm được có chức năng xuất xưởng.

Lưu ý bên lề: người gọi KHÔNG nên biết quá nhiều về bối cảnh của chính nó và mức ngữ cảnh của đối tượng được yêu cầu. Lý do: 1: rất dễ mắc lỗi (hoặc "thủ thuật thông minh") bằng cách chơi với các tham số này; 2: mức ngữ cảnh của yêu cầu có thể thay đổi sau này. Tôi chủ yếu kết nối thông tin ngữ cảnh với luồng, vì vậy kho đối tượng có thông tin mà không cần thêm tham số từ yêu cầu.

Mặt khác, yêu cầu có thể chứa gợi ý cho ví dụ: như nhận lãi suất cho một ngày cụ thể. Nó phải là cùng một quyền truy cập "toàn cầu", nhưng nhiều trường hợp tùy thuộc vào ngày (và dẫn các giá trị ngày khác nhau đến cùng một thể hiện giữa các thay đổi tốc độ), vì vậy nên thêm một đối tượng "gợi ý" vào yêu cầu, được sử dụng bởi nhà máy sản xuất và không phải là cửa hàng; và một keyForHint cho nhà máy, được sử dụng bởi các cửa hàng. Bạn có thể thêm các chức năng này sau, tôi chỉ đề cập.

Đối với trường hợp của bạn, đây là một loại quá mức (chỉ có một đối tượng được phục vụ ở cấp độ toàn cầu), nhưng đối với một mã bổ sung khá nhỏ và đơn giản ngay bây giờ, bạn có một cơ chế cho các yêu cầu phức tạp hơn, có lẽ phức tạp hơn.

Một tin tốt khác: nếu bạn ở Java, bạn nhận được dịch vụ này từ Spring mà không phải suy nghĩ quá nhiều, tôi chỉ muốn giải thích chi tiết về nó.


0

Lý do KHÔNG sử dụng toàn cầu (hoặc đơn) là vì mặc dù ban đầu bạn chỉ mong muốn có một giá trị, nhưng thật đáng ngạc nhiên khi có thể sử dụng cùng một mã nhiều lần trong cùng một chương trình:

  • để tính toán những gì sẽ xảy ra nếu lãi suất khác nhau
  • để có một số thành phần phụ thuộc vào lãi suất của Hoa Kỳ và một số thành phần phụ thuộc vào lãi suất của Vương quốc Anh

Tôi sẽ biến lãi suất thành thành viên của lớp "công cụ tài chính" và chấp nhận rằng bạn phải chuyển nó vào bất kỳ lớp thành viên nào (tính theo từng tính toán hoặc đưa cho chúng một con trỏ / móc vào nó khi xây dựng).


0

Mọi thứ nên được thông qua trong tin nhắn, không được đọc từ một điều toàn cầu.

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.