重构代码以避免反模式

2023-12-13

我有一个 BusinessLayer 项目,其中包含以下代码。域对象是FixedBankAccount(它实现了IBankAccount)。

  1. 存储库被制作为域对象的公共属性,并被制作为接口成员。如何重构它以使存储库不再是接口成员?

  2. 域对象(FixedBankAccount)直接使用存储库来存储数据。这是否违反单一责任原则?如何纠正呢?

注意:存储库模式是使用 LINQ to SQL 实现的。

EDIT

下面给出的代码是更好的方法吗?https://codereview.stackexchange.com/questions/13148/is-it-good-code-to-satisfy-single-responsibility-principle

CODE

public interface IBankAccount
{
    RepositoryLayer.IRepository<RepositoryLayer.BankAccount> AccountRepository { get; set; }
    int BankAccountID { get; set; }
    void FreezeAccount();
}
public class FixedBankAccount : IBankAccount
{
    private RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
    public RepositoryLayer.IRepository<RepositoryLayer.BankAccount> AccountRepository
    {
        get
        {
            return accountRepository;
        }
        set
        {
            accountRepository = value;
        }
    }

    public int BankAccountID { get; set; }

    public void FreezeAccount()
    {
        ChangeAccountStatus();
    }

    private void SendEmail()
    {

    }

    private void ChangeAccountStatus()
    {
        RepositoryLayer.BankAccount bankAccEntity = new RepositoryLayer.BankAccount();
        bankAccEntity.BankAccountID = this.BankAccountID;

        accountRepository.UpdateChangesByAttach(bankAccEntity);
        bankAccEntity.Status = "Frozen";
        accountRepository.SubmitChanges();
    }
}
public class BankAccountService
{
    RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
    ApplicationServiceForBank.IBankAccountFactory bankFactory;

    public BankAccountService(RepositoryLayer.IRepository<RepositoryLayer.BankAccount> repo, IBankAccountFactory bankFact)
    {
        accountRepository = repo;
        bankFactory = bankFact;
    }

    public void FreezeAllAccountsForUser(int userId)
    {
        IEnumerable<RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(p => p.BankUser.UserID == userId);
        foreach (RepositoryLayer.BankAccount repositroyAccount in accountsForUser)
        {
            DomainObjectsForBank.IBankAccount acc = null;
            acc = bankFactory.CreateAccount(repositroyAccount);
            if (acc != null)
            {
                acc.BankAccountID = repositroyAccount.BankAccountID;
                acc.accountRepository = this.accountRepository;
                acc.FreezeAccount();
            }
        }
    }
}
public interface IBankAccountFactory
{
     DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount);
}
public class MySimpleBankAccountFactory : IBankAccountFactory
{
    public DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount)
    {
        DomainObjectsForBank.IBankAccount acc = null;

        if (String.Equals(repositroyAccount.AccountType, "Fixed"))
        {
            acc = new DomainObjectsForBank.FixedBankAccount();
        }

        if (String.Equals(repositroyAccount.AccountType, "Savings"))
        {
            acc = new DomainObjectsForBank.SavingsBankAccount();
        }

        return acc;
    }
}

阅读:

  1. DDD - 实体状态转换

  2. https://codereview.stackexchange.com/questions/13148/is-it-good-code-to-satisfy-single-responsibility-principle

  3. 使用“单一职责原则”强制我的容器拥有公共设置器

  4. https://softwareengineering.stackexchange.com/questions/150760/single-responsibility-principle-how-can-i-avoid-code-fragmentation


我不会说这是一种反模式,因为反模式首先应该是一种模式(一种可识别的、广泛的做事方式),而且我不知道有任何“存储库” -领域-对象”模式。

然而,在我看来,这肯定是不好的做法,因为您的 BankAccount 域对象混合了 3 个职责:

  • 作为域对象,其自然且合法的责任是冻结自身并更改其状态。

  • 更新并将更改提交到持久存储的责任(使用 accountRepository)。

  • 有责任决定如何发送消息(在这种情况下为电子邮件)并发送。

结果,您的 Domain 对象与太多事物紧密耦合,使其僵化且脆弱。它可能会因为太多的原因而改变,甚至可能被破坏。

所以没有反模式,但违反了单一责任原则一定。

最后两个职责应该转移到单独的对象。提交更改更应该属于管理业务事务(工作单元)的对象,并且知道结束事务和刷新事物的正确时间。第二个可以放置在基础设施层的电子邮件服务中。理想情况下,执行全局冻结操作的对象不应该知道消息传递机制(通过邮件或其他方式),而应该注入它,这样可以提供更大的灵活性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重构代码以避免反模式 的相关文章

  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用.Net/C# 计算集合的频率分布

    是否有一种快速 简单的方法来使用 Linq 或其他方式计算 Net 集合的频率分布 例如 任意长的 List 包含许多重复项 遍历列表并计算 跟踪重复次数的巧妙方法是什么 查找列表中重复项的最简单方法是将其分组 如下所示 var dups
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 当我尝试上传 Microsoft 商店时,UWP/Xamarin 在提交测试中崩溃

    我正在使用 Xamarin Forms 开发一个带有 SignalR 的消息发送应用程序 我在本地和 Android 上测试了无数次 它运行良好 没有崩溃 但是当他们进行测试以将其上传到微软商店时 他们报告说我的应用程序崩溃了 根据应用程序
  • python 中 perluniprops 的等价物是什么?

    In perl 有perlunipropsUnicode 7 的索引 http perldoc perl org perluniprops html我可以执行以下操作来填充开始和结束标点符号 s p Open Punctuation 1 g
  • 为什么我无法设置 cookie 并重定向?

    我在设置 cookie 和执行操作时遇到问题302重定向在chrome中 cookie没有被设置 我没有测试过safari 在其他浏览器中我遇到了同样的问题 直到我添加Path 到 cookie 现在它可以工作了 这是标题的样子 状态是30
  • 为什么 Integer a=10 在 java 中是有效的语句? [复制]

    这个问题在这里已经有答案了 据我所知 Integer 是一个包装器class对于整数 所以必须创建一个对象来初始化a的值 Integer x new Integer 10 But Integer x 10 似乎工作完美 有人可以解释一下吗
  • 安装 coremltools 时出错

    我正在研究 Core ML Apple iOS 框架 我已经读过安装 coremltools 来创建自己的模型 我已经安装了pythonsudo python Users administrator Downloads get pip py
  • MongoDB 字段名称中不允许使用哪些字符?

    我当然明白了 和 SPACE 是不允许的 还有其他禁用字符吗 您可以在字段名称中使用任何不属于的 UTF8 字符 特殊 包含 或以 开头 https jira mongodb org browse SERVER 3229 https sta
  • 注入非角度 JS 库

    在我们的项目中 我们使用 NPM 和 Browserify 进行第三方依赖管理 它与 AngularJS 结合使用效果很好 感谢 CommonJS 模块 以下代码显示了依赖结构 它与 Angular 的依赖注入配合得很好 function
  • 如何使用末尾带有 # 的 Uri.parse()

    我尝试使用 GSM 代码通过 Android 应用程序转接电话 例如 如果我致电 21 otherNumber 我所有的电话都将转接至其他号码 My code Uri transfert Uri parse tel 21 numero In
  • C++ eof() 问题 - 永远不会返回 true?

    所以我正在尝试读取这个文件 一切看起来应该可以工作 但在运行时程序超时并停止工作 我必须关闭它 到底是怎么回事 我怀疑 oef 测试永远不会返回 true 并且它会不断在文件中查找更多内容 我没有在文本文件中拖动空行 我疯狂地尝试调试这个
  • 在 Windows 中找不到命令 php

    我已经在 Windows 7 中安装了 xampp 服务器 我已经检查了浏览器的工作情况 但我正在尝试运行 php v 命令提示符 我收到以下错误消息 php is not recognized as an internal or exte
  • 使用 Laravel 5.8 / Cashier / Stripe 设置订阅时遇到问题

    我按照这个教程一步步操作 https appdividend com 2018 12 05 laravel stripe payment gateway integration tutorial with example 然而 当我去测试它
  • 在文件中查找字符串的最快方法

    我有一个不超过 10KB 的日志文件 文件大小最大可达 2 MB 我想查找文件中是否至少出现一组这些字符串 这些字符串将位于不同的行 例如 行动 输入 结果 我至少需要知道文件中是否存在上述一组 我已经做了大约 100 次测试 每次日志都不
  • PHP 正则表达式在冒号之前转换文本以进行链接

    我需要找到第一次出现的冒号 并获取之前的完整字符串并将其附加到链接中 e g username twitter nice site RT www google com visited 需要转换为 a href http twitter co
  • 用于 Web 开发的 iOS Touch ID

    我目前正在尝试找到一种方法来构建响应式网站 但是一旦网站在 iOS 设备上加载 我想使用新的 iOS Touch ID api 来允许会员登录 我知道当然可以使用 Native 以及 Cordova 来做这样的事情 http cordova
  • 在 pagerAdapter 中的片段之间发送数据

    您好 我正在尝试在两个片段之间发送数据 armarFragment 到 cocinaFragment 但我不知道该怎么做 因为两者都在同一个 Activity tabsActivity 中 该 Activity 实现了 pagerAdapt
  • 位置之前的第一个索引

    我有一个字符串和该字符串中的索引 并且想要获取该索引之前的子字符串的第一个位置 例如 在字符串中 this is a test string that contains other string for testing 是否有一个函数 给定
  • Visual Basic .NET 中的 C 样式指针

    我研究 Visual Basic NET 中的 C 风格指针有一段时间了 我遇到过http support microsoft com kb 199 824 wa wsignin1 0但我不知道这是否正确或如何应用 我已经使用 c 中的程序
  • Angularjs 与 html5Mode 的正常链接

    我正在 html 5 模式下使用 angularjs 它似乎控制了页面上的所有 href 但是 如果我想要链接到应用程序同一域中但实际上不在应用程序中的某些内容 该怎么办 一个例子是 pdf If i do a href pdfurl An
  • 如何使用 Google 地图将地址地理编码为纬度/经度

    我希望能够在谷歌地图上绘制几家公司 并了解我需要对这些公司进行地理编码 我还在地图上的多个标记下方提供了代码 如何对多个公司地址进行地理编码 使用以下地址作为第一个示例 并将其合并到我当前的代码中 我真的需要有人的帮助 因为我无法理解 Go
  • 重构代码以避免反模式

    我有一个 BusinessLayer 项目 其中包含以下代码 域对象是FixedBankAccount 它实现了IBankAccount 存储库被制作为域对象的公共属性 并被制作为接口成员 如何重构它以使存储库不再是接口成员 域对象 Fix