方法依赖性 - 最佳实践?

时间:2012-10-18 20:09:46

标签: c# .net oop dependencies

处理方法依赖于执行的属性的最佳方法是什么?

假设您有一个具有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,则会出现错误。因此,您似乎必须验证在方法中设置了这些属性。

第二个示例强制用户提供执行该方法所需的数据。但是,这似乎有点多余,因为传入的参数已经是对象的属性。

有没有“最好”的方法来做到这一点?

提前致谢。

5 个答案:

答案 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;
}

顺便说一下,让实体坚持下去并不是一个好主意:)