处理方法依赖于执行的属性的最佳方法是什么?
假设您有一个具有2个属性的类和一个使用这两个属性执行某些操作的方法。是否更好地实例化类,设置属性,然后执行方法(没有参数);或实例化该类,然后执行该方法,传入将设置属性的参数?
例如:
class Person ...
string Name ...
string Address ...
void Save() {
Database.SavePerson(this.Name, this.Address);
}
---或---
class Person ...
string Name ...
string Address ...
void Save(string name, string address) {
this.Name = name;
this.Address = address;
Database.SavePerson(this.Name, this.Address);
}
在第一个示例中,如果在调用Save方法之前尚未设置Name和Address,则会出现错误。因此,您似乎必须验证在方法中设置了这些属性。
第二个示例强制用户提供执行该方法所需的数据。但是,这似乎有点多余,因为传入的参数已经是对象的属性。
有没有“最好”的方法来做到这一点?
提前致谢。
答案 0 :(得分:2)
首先,我会考虑是否让实体负责自己的持久性是你想要的设计。
如果没有,则Person
实体将公开属性,另一种类型将负责保存Person
实体(例如,如果使用类似Repository模式的情况则会出现这种情况)
如果实体负责持久化(如果您使用的是富域模型,例如与CSLA等框架一起使用的那种情况),那么您将只有一个无参数的Save
方法,如果需要属性,那么某种形式的验证框架将捕获任何缺失的要求。
答案 1 :(得分:2)
就个人而言,我不会这样做。你拥有的第一个例子类似于Active Record,而第二个例子对我来说毫无意义,如果函数接受了参数,那么拥有字段/属性有什么意义呢?
这两种方法的问题是Person
类暴露了您可能不需要的数据库逻辑。
我要做的是使用存储库模式:
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
}
public class PersonRepository()
{
public void Add(Person person)
{
// do some database stuff
}
}
// ...
Person person = new Person() { Name = "Jim", Address = "123 Fake Street" };
PersonRepository personRepository = new PersonRepository();
personRepository.Add(person);
答案 2 :(得分:0)
如果参数可以某种方式推导/解决,或者它们永远不会改变,那么只允许方法无参数。
否则它会变成d leaky abstraction,您需要了解该方法的工作原理才能使用它。
答案 3 :(得分:0)
要么你有一个实例方法会自动使用没有参数的属性,或者你有一个静态方法接受传递给它的任何参数
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public void Save()
{
Database.SavePerson(Name, Address);
}
public static void Save(string name, string address)
{
Database.SavePerson(name, address);
}
}
对象的一般概念是每个对象都对其自己的数据负责。但是,类可以具有可以全局使用的静态方法,并且不绑定到任何对象实例。静态方法无法访问实例成员。
但基本问题是保存方法是否应该包含在Person
类中。相反,我会将Database.SavePerson
方法的参数列表更改为
public static void SavePerson(Person person) { ... }
并像这样使用
var p = new Person { Name = "John", Address = "Wall Street, NY" };
Database.SavePerson(p);
答案 4 :(得分:0)
我想到的是 - 您通过此方法打破了Single Responsibility Principle。因为您执行三个事物 - 持久化实体,AND重命名人员,并更改其地址。从方法名称来看,这一点并不清楚。这是副作用。
因此,要告知开发人员您的方法确实做了什么,您应该将其重命名为SaveAndRenameAndRelocate
。不是很好的名字?同意。
因此,我创建了无参数方法,用于将实体保存在当前状态。
public void Save()
{
// code, which should be somewhere in repository
}
如果您需要重命名人员 - 请通过Name属性进行操作。如果您需要更改地址 - 请通过地址属性进行更改。如果不允许保存没有名称和/或地址的人 - 通过构造函数初始化这些属性:
public Person(string name, string address)
{
// null-check goes here
Name = name;
Address = address;
}
顺便说一下,让实体坚持下去并不是一个好主意:)