理性探讨:为啥业务层需要一个service接口,一个impl实现类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理性探讨:为啥业务层需要一个service接口,一个impl实现类相关的知识,希望对你有一定的参考价值。
参考技术A 为什么业务层需要一个service接口,一个impl实现类,而不直接调用impl里的实现方法呢。为啥我们的项目需要接口层/抽象类? [关闭]
【中文标题】为啥我们的项目需要接口层/抽象类? [关闭]【英文标题】:Why Interface Layer/Abstract classes required in our project? [closed]为什么我们的项目需要接口层/抽象类? [关闭] 【发布时间】:2012-03-30 21:59:31 【问题描述】:我们通常在项目中使用抽象函数/接口。为什么真的需要它?为什么我们不能只选择业务逻辑层、数据访问层和表示层
表示层中的功能:
abc();
业务逻辑层的功能:
public void abc()
//Preparing the list
数据访问层的功能:
public abstract void abc();
数据访问 SQLServer 层中的功能:
public override void abc()
//Connection with database
问题是:为什么需要数据访问层?
【问题讨论】:
【参考方案1】:imo 理解这一点的最简单方法是对DataLayer
进行抽象。
您已经设置了一个函数来从xml
文件中检索数据。但是有一天你的产品会横向扩展,xml
还不够像数据存储。所以你传递给一些嵌入式数据库:sqlite
。但是有一天,您需要在某些企业环境中重用您的库。因此,现在您需要开发对sqlserver
、oracle
、webservice
...的访问权限。在所有这些更改中,您需要更改不仅实际访问数据的代码,而且实际上也使用它的代码。多年来,您在客户端上的第一个 xml
数据访问已经使用了多年并且对此感到满意的代码呢?后向兼容性如何?
如果不直接解决大部分此类问题,那么抽象肯定可以使您的应用程序具有可扩展性,并且更能抵抗变化,在我们的世界中,这种变化有时发生得太频繁了。
【讨论】:
我的问题得到了改进。对吧?需要投票才能重新打开它.... 我之前没有投票赞成关闭它。 当您说“向后兼容性如何?”时无法理解。能不能说的更精确一点? 或者你能举个例子吗? 如果您的应用程序在所有架构变化中都有一个抽象层来访问数据,对于使用本地xml
文件的客户端在更新到最新版本后不会有太大变化您使用 Azure
的应用程序。您有一个使用相同集合的单一抽象函数:在访问xml
之前和访问cloud
之后。如果您的程序中有 5 年前由第三方开发人员编写的代码,则无需触摸该代码即可继续完美运行,无需任何关于真实数据源的特殊知识。【参考方案2】:
通常,如果您在代码中使用接口,那么您将以依赖注入的形式获得代码可操作性。
这将帮助您在某些情况下替换部分实现,例如在单元测试期间提供 Mock 对象。
【讨论】:
你也可以在这里加入聊天chat.***.com/rooms/8875/…【参考方案3】:为什么接口: 你有没有在 c# 中使用过 using : 使用 (Form f = new Form())
在这里您将看到您只能使用 using 中实现 IDisposable 接口的那些类。
两个互不认识的事物只能通过接口进行交互。 接口保证“某些”功能肯定是由这种类型实现的。
为什么要分层:
这样您就可以拥有单独的 dll,让您可以在不同的应用程序中重用。
基本上都是为了代码重用和性能提升。
【讨论】:
接口保证“某些”功能肯定已经被这种类型实现了。所以我需要在完整的项目中追踪所有接口的实现!!! 不是这样。我们不会为自己编写接口。实现接口的代码/类告诉别人“嘿,看”,“我就是这种类型,你可以使用我”。例如您的 PC USB 插座。想象一下,您创办了一家价值 10 亿美元的公司,提供 USB - 超快、便宜等。但唯一的问题是,您连接到 PC 的 USB 区域可以说是 Hexagonal。您还创建了自己的计算机,该计算机具有用于此 USB 的六角端口。现在告诉我,你的 USB 可以被全世界使用吗?当然不是!您的 USB 提供的 INTERFACE 与其他 PC 不匹配。 但是USB可以被你的电脑使用,因为它有六角插座。只需将 USB=Data 访问层和您的计算机视为 UI 层。如果您不希望其他项目使用您的数据访问层,那么“您不需要任何接口”。这个例子代表了你为什么需要接口的一小部分,还有更多……谷歌它们,你会发现更多。您的 USB 将只在您身边,无论它多么快速和便宜,它对其他人没有用,只有您可以使用它。 我的每个项目都是一个单独的项目。松散耦合。 如果你愿意将你的层分享给外界,那么你可能需要有接口。 Abstarct 类有不同的用途(有时使用接口的实现可以等同于抽象类,但请注意......它们是不同的东西。例如 1 / 1 和 1 * 1 都等于 1,这并不意味着除法和乘法是一样的。【参考方案4】:我认为您在谈论 Facade 层。
这是一个可选层,它将简化业务层的功能。让我们想象一下,您有一个 ProductManager 和 CategoryManager,并且您想要执行一个涉及使用两者的特定操作(例如,让我获得所有类别中的前 5 个产品),那么您可以使用一个使用 ProductManager 和 CategoryManager 的外观层。
灵感来自Facade Pattern。
【讨论】:
【参考方案5】:抽象有助于创建功能,无论是通过基类、接口还是组合,如果使用得当,可以为代码的维护、可读性和可重用性带来奇迹。
关于问题中发布的代码,标记为“数据访问层”的代码充当业务层使用的通用抽象。通过这样做,DAL 的具体实现(例如示例中的“数据访问 SQLServer 层”下的内容)与业务层分离。现在您可以实现访问不同数据库的 DAL,或者自动提供数据进行测试等。
存储库模式是 DAL 中的一个很好的示例(示例已简化):
public interface IProductRepository
Product Get(int id);
...
public class SqlProductRepository : IProductRepository
public Product Get(int id) ...
...
public class MockProductRepository : IProductRepository
private IDictionary<int, Product> _products = new Dictionary<int, Product>()
1, new Product() Name = "MyItem"
;
public Product Get(int id) return _products[id];
...
public class AwesomeBusinessLogic
private IProductRepository _repository;
public AwesomeBusinessLogic(IProductRepository repository)
_repository = repository;
public Product GetOneProduct()
return _repository.GetProduct(1);
尽管此示例使用接口,但同样适用于基类的使用。美妙之处在于,现在我可以将SqlProductRepository
或MockProductRepository
输入AwesomeBusinessLogic
并且不必更改AwesomeBusinessLogic
的任何内容。如果出现另一种情况,所需要的只是IProductRepository
的新实现,AwesomeBusinessLogic
仍将处理它而无需更改,因为它仅通过接口访问存储库。
【讨论】:
现在您可以实现访问不同数据库的 DALMicrosoft 企业库在 DAL 层为我完成这项工作。 是的,MS Enterprise 库将帮助您实现这一目标,但是如果您决定将您的存储库现在公开为 Web 服务,如 WCF 数据服务(也称为 ado.net 数据服务),该怎么办? ??如果您已将存储库创建为接口,那么替换它很容易——这就是全部内容...希望您现在清楚。 没有得到你..老实说。如何在您的架构中包含 WCF?好的,为什么 WCF 不能直接与 DataBase 层交互?每一层都是一个独立的项目。【参考方案6】:前面所有的答案可能都说明了抽象层的需求,但我还是想补充一些自己的想法。
假设在我们的项目中,每一层只有一个服务实现。例如,我有一个联系人 DAL 和一个联系人 BLL 服务,我们可以这样做
namespace ***
public class ContactDbService
public Contact GetContactByID(Guid contactID)
//Fetch a contact from DB
联系 BLL 服务:
namespace ***
public class ContactBLLService
private ContactDbService _dbService;
public ContactBLLService()
_dbService = new ContactDbService();
public bool CheckValidContact(Guid contactID)
var contact = _dbService.GetContactByID(contactID);
return contact.Age > 50;
没有定义接口/抽象类。
如果我们这样做,就会有一些明显的缺点。
代码交流: 想象一下,如果你的项目涉及到,你的服务可能有很多不同的方法,一个维护者(除了你)怎么可能知道你的服务是做什么的呢?他是否必须阅读您的整个服务才能修复像 InvalidCastOperation 这样的小错误? 通过查看界面,人们将立即了解服务的功能(至少)。
单元测试
您可以使用 fake/mock 服务测试您的逻辑,以提前检测错误并防止以后发生回归错误。
更容易改变:
通过只引用其他类中的接口/抽象类,您可以在以后轻松替换那些接口实现,而无需太多工作。
【讨论】:
通过只引用其他类中的接口/抽象类,您以后可以轻松替换那些接口实现,而无需太多工作。这可以通过直接在DAL 层。为什么是接口? 通过查看界面,人们将立即了解服务的功能(至少)。 我们通常根据模块和特定需求创建功能名称。为什么是接口? 我们通常根据模块和具体需要创建函数名称。为什么是接口?如果我没有对您的功能的任何描述,我怎么知道您的班级可以做什么?为了知道我应该从 BLL 中调用什么,我是否必须搜索并阅读您类的所有函数? 你是想在函数的标题部分说 cmets 吗? 不,我的意思是,假设您开发服务,稍后我将接您的工作并继续。我怎么知道你们的服务细节? 基本上有两种方式。 1. 按 Ctl + M + o 这将只显示隐藏在 DAL 层中的函数名称和函数定义。 2. 实例化类和类型对象。这将向您显示包含您定义的函数 cmets 摘要的完整函数列表。为什么是接口呢?【参考方案7】:抽象类或接口实际上并不是一个单独的层 - 它应该是业务逻辑层的一部分,它定义了实际数据访问层(例如 SQL 数据存储库)需要实现以提供数据的接口访问业务层的服务。
如果没有这个接口,你的业务层将直接依赖于 SQL 层,而接口消除了这种依赖:你将抽象类或接口放入业务逻辑层。然后 SQL 层(例如,一个单独的程序集)实现抽象类/接口。这样 SQL 层依赖于业务层,而不是相反。
结果是一个具有独立业务层的灵活应用程序,可以与多个数据存储库一起使用 - 它所需要的只是一个实现业务层定义的接口的层。而且它不仅仅是关于数据存储库——你的业务层不应该依赖于上下文(asp.net、控制台应用程序和服务等),它不应该依赖于用户界面类、模块接口与您的业务应用程序等。
【讨论】:
为什么要为 Interface/Abstract 类创建依赖项。基本需求是什么?有什么安全措施吗?【参考方案8】:抽象使您能够快速进行重构。考虑不使用 SQL 服务器,而是决定使用其他提供程序;如果您没有数据访问层,那么您需要进行巨大的重构,因为您直接调用数据访问方法。但是如果你有一个数据访问层,你只需要编写一个新的数据访问层,继承自你的抽象数据访问层,你不会改变业务层中的任何东西。
【讨论】:
以上是关于理性探讨:为啥业务层需要一个service接口,一个impl实现类的主要内容,如果未能解决你的问题,请参考以下文章