【问题标题】:Make method to do difference in specific situation在具体情况下做不同的方法
【发布时间】:2014-08-22 12:31:37
【问题描述】:

在命名空间com.example.website.domain.model,我有Project类,见代码:

public class Project
{
    private string Name;
    private int Status = 0;
    ... And much more attributes ....

    public Project(string name) {
        Name = name;
    }

    public void Publish()
    {
        Status = 1;
    }

    public bool IsPublished()
    {
        return Status == 1;
    }

    public void ChangeName(string newName)
    {
        if (IsPublished()) throw new InvalidOperationException("Not allow to change name after published");
        Name = newName;
    }

    public string GetName()
    {
        return Name;
    }

    ... And much more method ...
}

在正常情况下,如果项目尚未发布,用户可以更改项目名称。

我必须创建能够更改名称的管理页面,即使项目已发布。我考虑将新方法添加到Project,即public void AdminChangeName(string name)。但我认为Project 不应该在管理部分(命名空间)之外公开​​这种方法。我想在没有验证的情况下调用具有相同签名的相同方法。

【问题讨论】:

  • 我认为拥有一个不包含该验证的单独 AdminChangeName(...) 函数非常好。您的管理员可能会更改已发布项目的名称,而用户可能不会,这似乎是一个合适的业务用例。应用层应确保该函数仅由管理员调用(授权)。

标签: c# oop domain-driven-design software-design


【解决方案1】:

定义动态多态性(这是您所需要的)的唯一方法是创建某种组合。那就是你必须在一些新类中提取检查逻辑。

让我们看一些例子。

1.

//in domain namespace
public interface INameChangeStrategy {
    public void ChangeName(Project project, string name);
} 

//in general use namespace
public class DefaultNameChangeStrategy : INameChangeStrategy {
    public void ChangeName(Project project, string name) {
        if (project.IsPublished()) throw new InvalidOperationException("Not allow to change name after published");
        project.setName(name);
    }
}

//in admin use namespace
public class AdminNameChangeStrategy : INameChangeStrategy {
    public void ChangeName(Project project, string name) {
        project.setName(name);
    }
}

如您所见,问题在于违反封装。项目本身“信任”策略并打开其名称属性以直接更改(方法 .setName(...))。 此外,您还必须根据使用环境正确配置策略 - 管理员与否。

2.

另一个相同的解决方案 - 在 Project 类中添加策略:

界面类似

public interface INameChangeCheckStrategy {
    public CanChangeName(Project project, string name);
} 

//in general use namespace
public class DefaultNameChangeCheckStrategy : INameChangeCheckStrategy {
    public void ChangeName(Project project, string name) {
        if (project.IsPublished()) throw new InvalidOperationException("Not allow to change name after published");
        //other check logic, i.e. regex match
    }
}

public class Project
{
    private INameChangeCheckStrategy _nameChangeAbilityStrategy;
    ...
    public void ChangeName(string newName)
    {
         _nameChangeAbilityStrategy.CanChangeName(this, newName);
         name = newName;
    }
}

在这种情况下,封装处于更高级别。

最重要的是策略实现必须是运行时每个请求的实例,因此项目实例要根据请求正确初始化

【讨论】:

    【解决方案2】:

    发布后只有管理员角色可以更改名称?如果答案是肯定的,这是我的答案:

    您正在混合关注点、权限或角色验证属于应用程序关注点而不是您的域(在本例中为 Project 类)。

    因此,您不应该为同一操作使用不同的方法,而是在更改名称之前验证项目是否已发布并且用户具有管理员角色。

    我非常推荐这个视频,它讲述了如何分离关注点SOLID architecture in slices not layers

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      相关资源
      最近更新 更多