将实体保存到数据库 - 我的Save方法应该返回保存的实体吗?

时间:2012-12-05 06:31:29

标签: c# refactoring

所以,我认为有一个Save方法没有返回刚刚成功保存的实体,这有点奇怪。但是,传入Save的实体会被函数修改。

示例:

//T SaveOrUpdate(T entity); from IDao
PlaylistDao.SaveOrUpdate(playlist);

此功能获取播放列表,将其保存到数据库,然后返回已保存的播放列表。但是,传递给SaveOrUpdate的参数是引用等于它的返回值。

考虑到这一点,这是一个更清晰的实施:

public void SavePlaylist(Playlist playlist)
{
    try
    {
        NHibernateSessionManager.Instance.BeginTransaction();
        PlaylistDao.SaveOrUpdate(playlist);
        NHibernateSessionManager.Instance.CommitTransaction();
    }
    catch (Exception exception)
    {
        Logger.Error(exception);
        throw;
    }
}

vs

public Playlist SavePlaylist(Playlist playlist)
{
    Playlist savedPlayist;
    try
    {
        NHibernateSessionManager.Instance.BeginTransaction();
        savedPlayist = PlaylistDao.SaveOrUpdate(playlist);
        NHibernateSessionManager.Instance.CommitTransaction();
    }
    catch (Exception exception)
    {
        Logger.Error(exception);
        throw;
    }

    return savedPlayist;
}

我认为第二个功能对于之前没有看过代码的人来说更清楚,但是一旦开发人员理解,第一个实现就更简洁,更清晰。有什么想法吗?

更新:要明确,SaveOrUpdate会对播放列表产生副作用。将播放列表保存到数据库时,其ID字段将使用DB提供的值进行更新。

5 个答案:

答案 0 :(得分:4)

我会选择第一种方法,但只需稍加改动 - 将参数传递给ref。 (请参阅注释。)我遇到的问题是你不必要地创建了一个额外的变量。为什么不在第一个方法中添加一些<summary>标签,在intellisense中指出将要发生什么以澄清任何混淆?对我来说,这比创建一个额外的变量基本上做同样的事情要好。

答案 1 :(得分:1)

在第一个方法中,您只是返回参数值而没有任何改变并带有副作用。我认为它不清楚或有用。你的第二种方法似乎更有用。

编辑:基于评论。

我不认为,你的方法SaveOrUpdate应该做这样的事情。最好返回一个值,如果出现某种异常或由于您想要做的任何意外情况,该怎么办:

playerlist = null;

SaveOrUpdate方法中,您不会在SavePlaylist方法中看到对原始对象的影响。由于对象引用是通过值:)传递的。而在你的第二种方法中,它会对物体产生影响,并且会更清楚地反映出来。如果使用ref关键字传递参数,则第一种方法会更清晰。

答案 2 :(得分:0)

也许返回布尔值会更好?如果出现问题,会有误吗?那么很容易检查返回值

答案 3 :(得分:0)

我想这更偏向于基础,重要的是选择一个模型并坚持下去。

我个人认为第二种方法是最好的。这是我的理由。

  • 保存方法有副作用,即它改变传递给它的对象。即使这些更改可通过对象引用返回给调用者,而对象读取代码的人可能无法完全看到,但实际上并未查看保存方法。

我认为第一行传达了修改对象的想法,而不是下一行

// Side effect is better understood
paylist = PlaylistDao.SaveOrUpdate(playlist);

// Side effect is not obvious unless looked into the SaveOrUpdate method.
PlaylistDao.SaveOrUpdate(playlist);

这就是为什么有些人喜欢功能语言而不是程序语言,因为功能语言不允许副作用,但强制返回修改后的值。即使您没有使用函数式语言,我认为遵循这种模式也有好处。

  • 其他原因是,返回修改后的值可以构建一个更好用的流畅的API,(只有在向播放列表类添加方法时,当你拥有SaveOrUpdate时,这并不适用)关于DAO的方法。

例如,如果您始终从方法中返回新对象,则可以进行类似。

的调用
playlist.SaveOrUpdate().WriteToLog(); // Something like this.

答案 4 :(得分:-1)

第二次尝试在系统中留下两个列表。带有无效条目的播放列表和带有效条目的savedPlaylist(有效=当前)。 Ooops,当发生异常时,savedPlaylist无效且播放列表仍然有效......问题?

第一次尝试总是会让播放列表具有当前值。要么全部都保存并更新,新实例具有唯一ID等,或者没有任何更改,列表仍包含未保存的数据。

BTW:我不认为PlayList是通过引用传递的。列表实例本身不会被修改,只会修改其内容。即使实例本身会发生变化,这些变化也会在方法之外隐藏,因为方法本身仅将参数'Playlist'声明为输入。