gpt4 book ai didi

c# - 业务对象之间过度可访问且极度耗费资源的关系。我怎样才能解决这个问题?

转载 作者:太空狗 更新时间:2023-10-29 23:19:11 25 4
gpt4 key购买 nike

首先,这似乎是一个很长的问题。我不认为它是......代码只是我目前正在做的事情的概述。感觉不对,所以我正在寻找建设性的批评和警告,以寻求对我可以做什么的陷阱和建议。

我有一个包含业务对象的数据库。
我需要访问父对象的属性。
我需要通过业务对象维护某种状态。

如果您查看类,我认为访问修饰符不正确。我认为它的结构不是很好。大多数关系都是用公共(public)属性建模的。 SubAccount.Account.User.ID <-- 所有这些都是公开的..

有没有比这更好的方法来模拟类之间的关系,使其不那么“公开”?

这个问题的另一部分是关于资源的:

如果我要创建一个返回 List 的 User.GetUserList() 函数,并且我有 9000 个用户,当我调用 GetUsers 方法时,它将创建 9000 个用户对象,并在其中创建 9000 个新的 AccountCollection 对象。我该怎么做才能使这个项目不那么耗费资源?

请找到下面的代码并将其撕成碎片。

public class User {

public string ID {get;set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string PhoneNo {get; set;}

public AccountCollection accounts {get; set;}

public User {
accounts = new AccountCollection(this);
}

public static List<Users> GetUsers() {
return Data.GetUsers();
}

}

public AccountCollection : IEnumerable<Account> {
private User user;

public AccountCollection(User user) {
this.user = user;
}

public IEnumerable<Account> GetEnumerator() {
return Data.GetAccounts(user);
}
}


public class Account {

public User User {get; set;} //This is public so that the subaccount can access its Account's User's ID
public int ID;
public string Name;

public Account(User user) {
this.user = user;
}

}

public SubAccountCollection : IEnumerable<SubAccount> {
public Account account {get; set;}

public SubAccountCollection(Account account) {
this.account = account;
}

public IEnumerable<SubAccount> GetEnumerator() {
return Data.GetSubAccounts(account);
}
}


public class SubAccount {
public Account account {get; set;} //this is public so that my Data class can access the account, to get the account's user's ID.

public SubAccount(Account account) {
this.account = account;
}

public Report GenerateReport() {
Data.GetReport(this);
}

}


public static class Data {

public static List<Account> GetSubAccounts(Account account) {

using (var dc = new databaseDataContext()) {
List<SubAccount> query = (from a in dc.Accounts
where a.UserID == account.User.ID //this is getting the account's user's ID
select new SubAccount(account) {
ID = a.ID,
Name = a.Name,
}).ToList();
}

}

public static List<Account> GetAccounts(User user) {

using (var dc = new databaseDataContext()) {
List<Account> query = (from a in dc.Accounts
where a.UserID == User.ID //this is getting the user's ID
select new Account(user) {
ID = a.ID,
Name = a.Name,
}).ToList();
}
}

public static Report GetReport(SubAccount subAccount) {

Report report = new Report();
//database access code here
//need to get the user id of the subaccount's account for data querying.
//i've got the subaccount, but how should i get the user id.
//i would imagine something like this:
int accountID = subAccount.Account.User.ID;
//but this would require the subaccount's Account property to be public.
//i do not want this to be accessible from my other project (UI).
//reading up on internal seems to do the trick, but within my code it still feels
//public. I could restrict the property to read, and only private set.

return report;
}

public static List<User> GetUsers() {

using (var dc = new databaseDataContext()) {
var query = (from u in dc.Users
select new User {
ID = u.ID,
FirstName = u.FirstName,
LastName = u.LastName,
PhoneNo = u.PhoneNo
}).ToList();

return query;
}
}

}

最佳答案

这个答案最终包含了很多流行词标题。希望我解释每一个以及为什么它适用于此。我认为我在下面介绍的每个概念都值得考虑 - 它们并不总是适用,但我发现它们都是我个人认为在考虑系统结构时有值(value)的东西。

单一职责

首先考虑每个对象的责任 - 它的工作是什么?通常,一旦您为每个类(class)决定了一项工作,您就会找到更好的设计。目前,您的许多类都做得太多,持有本应作为服务真正存在的逻辑。

上面的第一个例子是你的用户类:

public class User { 

public string ID {get;set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string PhoneNo {get; set;}

public AccountCollection accounts {get; set;}

public User {
accounts = new AccountCollection(this);
}

public static List<Users> GetUsers() {
return Data.GetUsers();
}

}

为什么要提供从数据源中获取用户的方法呢?该功能应该移出到用户服务中。

另一个关键示例是 SubAccount 上的 GenerateReport 方法 - 不要让您的报告生成逻辑与 SubAccount 对象紧密相关。将其拆分出来将为您提供更大的灵 active ,并减少对您的 SubAccount 的更改更改会破坏报告逻辑。

延迟加载

再次查看您的用户类 - 为什么它在实例化时加载所有用户帐户?每次与用户合作时,是否总是要使用这些对象?

引入延迟加载通常会更好 - 只在需要时检索帐户。当然,有时您需要预先加载(如果您知道很快就会需要该对象,所以不想减少数据库访问),但您应该能够针对这些异常进行设计。

依赖注入(inject)

这种从惰性加载点和单一职责点开始的后续。您有很多对数据类等内容的硬编码引用。这使您的设计更加严格 - 重构您的数据访问以引入延迟加载,或者更改用户记录的检索方式变得更加困难,因为许多类都直接访问数据访问逻辑。

摘要对象

向 Cade Roux 致敬 - 我从未听说过 Digest 对象这个词,通常称它们为轻量级 DTO。

正如 Cade 所说,如果您所做的只是显示绑定(bind)到唯一 ID 的用户名组合框,则没有理由检索包含功能齐全的用户对象的丰富列表。

引入一个只存储最基本用户信息的轻量级用户对象。

这又是引入服务/存储库抽象和某种依赖注入(inject)的另一个原因。当您将数据检索与实际对象封装在一起,并且您没有紧密绑定(bind)到数据访问实现时,更改从数据存储检索的对象类型会变得容易得多。

得墨忒耳法则

您的对象对彼此的内部结构了解得太多了。允许通过用户向下钻取到帐户,然后再向下钻取到子帐户混淆了每个对象的责任。您可以在不应该的情况下从用户对象设置子帐户信息。

我一直在为这个原则而苦恼,因为钻取层次结构似乎很方便。问题是它会阻止你深入思考每个对象的封装和作用。

也许不要向用户公开您的 Account 对象 - 而是尝试引入公开 Account 对象相关成员的属性和方法。查看 GetAccount 方法而不是帐户属性,这样您就可以强制自己使用帐户对象而不是将其视为用户的属性。

关于c# - 业务对象之间过度可访问且极度耗费资源的关系。我怎样才能解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2564767/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com