我的其中一位开发人员的代码类似于以下代码段
class Data
{
public string Prop1
{
get
{
// return the value stored in the database via a query
}
set
{
// Save the data to local variable
}
}
public void SaveData()
{
// Write all the properties to a file
}
}
class Program
{
public void SaveData()
{
Data d = new Data();
// Fetch the information from database and fill the local variable
d.Prop1 = d.Prop1;
d.SaveData();
}
}
class Data
{
public string Prop1
{
get
{
// return the value stored in the database via a query
}
set
{
// Save the data to local variable
}
}
public void SaveData()
{
// Write all the properties to a file
}
}
class Program
{
public void SaveData()
{
Data d = new Data();
// Fetch the information from database and fill the local variable
d.Prop1 = d.Prop1;
d.SaveData();
}
}
此处Data类属性动态地从DB获取信息。当需要将数据保存到文件时,开发人员创建实例并使用自我赋值填充属性。然后最后调用一个保存。我试图争论财产的使用是不正确的。但他并不相信。
这是他的观点
这种用法是否正确?
答案 0 :(得分:17)
我不认为使用相同代码的其他开发人员会很高兴看到:
d.Prop1 = d.Prop1;
我个人不会这样做。
使用属性从DB加载数据也不是最佳选择。
我会method
将数据从DB加载到本地变量,然后您可以使用属性获取该数据。此外,get/set
在逻辑上也必须使用相同的数据。使用get
从数据库获取数据但使用set
处理局部变量很奇怪。
答案 1 :(得分:4)
属性应该尽可能轻量级。
当其他开发人员使用属性时,他们希望它们是对象的内在部分(即已经加载并在内存中)。
这里的真正问题是对称性 - 属性get和set应该相互映射,而它们不会。这与大多数开发人员通常所期望的相反。
不建议从数据库加载属性 - 通常会通过特定方法填充类。
答案 2 :(得分:3)
“正确”通常是旁观者的眼睛。这也取决于您希望您的设计达到多远或多么出色。我永远不会选择你描述的设计,在POCO上进行CRUD操作将成为维护的噩梦。
您的主要问题是缺少 关注点分离 。即,数据对象还负责存储和检索(需要在整个系统中仅定义一次的动作)。因此,您最终会遇到重复,膨胀且无法维护的代码,这些代码很快就会变得非常慢(尝试使用gettor上的连接进行LINQ查询)。
数据库的一个常见场景是使用仅包含属性的小实体类,仅此而已。 DAO层负责使用数据库中的数据检索和填充这些POCO,并仅定义CRUD操作(通过一些泛型)。我建议使用NHibernate进行ORM映射。这里解释的基本原理也适用于其他ORM映射器,并且是explained here。
原因,尤其是nr 1,应该是将其重构为更易维护的主要候选者。遇到重复的代码和逻辑时,应该强烈重新考虑。如果上面的gettor真的得到了数据库数据(我希望我误解了),尽快摆脱它。
关注点分离的过度简化示例:
class Data
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
}
class Dao<T>
{
SaveEntity<T>(T data)
{
// use reflection for saving your properies (this is what any ORM does for you)
}
IList<T> GetAll<T>()
{
// use reflection to retrieve all data of this type (again, ORM does this for you)
}
}
// usage:
Dao<Data> myDao = new Dao<Data>();
List<Data> allData = myDao.GetAll();
// modify, query etc using Dao, lazy evaluation and caching is done by the ORM for performance
// but more importantly, this design keeps your code clean, readable and maintainable.
编辑:
你应该问你的同事一个问题:如果你有很多数据(数据库中的行),或者属性是连接查询(外键表)的结果,会发生什么。如果您希望从一种情况(不可维护)平稳过渡到另一种情况(可维护),那么请查看Fluent NHibernate,这很容易被任何人理解。
答案 3 :(得分:3)
这非常糟糕,imo。
d.Prop1 = d.Prop1
看起来像<无意义的自我分配,而不是“从数据库加载数据”调用。答案 4 :(得分:1)
如果我是你,我会写一个序列化/反序列化函数,然后提供属性作为内存结果的轻量包装。
查看ISerialization接口:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx
答案 5 :(得分:1)
这很难处理,
如果您设置Prop1,然后获取Prop1,您可能会得到不同的结果 例如:
//set Prop1 to "abc"
d.Prop1 = "abc";
//if the data source holds "xyz" for Prop1
string myString = d.Prop1;
//myString will equal "xyz"
在没有评论的情况下阅读代码,你会发现mystring等于“abc”而不是“xyz”,这可能会令人困惑。
这将使得处理属性非常困难,并且每次更改属性时都需要保存才能使其工作。
答案 6 :(得分:0)
在我看来,这是一个糟糕的设计。使用属性getter做一些“神奇”的东西会使系统难以维护。如果我加入你的团队,我怎么知道这些属性背后的魔力?
创建一个在行为时调用的单独方法。
答案 7 :(得分:0)
除了同意其他人在此示例中所说的内容之外,如果Data类中还有其他字段会发生什么?即Prop2,Prop3等,每次访问它们时都会返回数据库,以“通过查询返回存储在数据库中的值”。 10个属性将等于10个数据库命中。设置10个属性,10写入数据库。这不会扩大规模。