我是一名经验丰富的.NET开发人员,主要从事网络表单工作。我熟悉MVC但尚未商业化使用。我目前正在这个领域进行一些自我教育,并且对建筑学主题的意见分歧感到有些困惑,让我在这个问题的前面加上一个理解,即没有正确或错误的答案,但我只是在寻求什么是一个优雅的解决方案。
我将首先说我没有使用实体框架或任何类型的ORM - 我想直接实现我自己的业务对象和数据访问代码(使用ADO,SPROCS等)以确保它们是最佳的,这是个人偏好。这是我努力寻找一致信息的地方,因为看起来大多数信息都与使用LINQ to SQL或实体框架有关。
MY应用程序的结构包括以下项目:
只有两个项目,因为我遇到问题解耦;这是我问题的根源。 我的模型类库包含...
我遇到的问题是所有这些层之间的依赖关系。它感觉不对劲!
1.业务对象应该包含实现业务逻辑的方法,除了字段和属性之外还有实现任何所需逻辑的方法吗?
2.存储库类执行数据访问代码但是知道业务对象,这也感觉不对,数据访问代码应该位于自己的类库中,对这些对象一无所知?
3.控制器(在Web层中)利用存储库接口,但为什么?它们不应该包含业务逻辑,“模型”或业务对象应该包含哪些?控制器当然不应该包含业务逻辑,所以这是不对的。我不希望存储库中存在业务逻辑,因为它们正在访问数据库。
我正在努力为应用程序找到一个优雅的架构,只是一个基本的概述如何实现我自己的对象,我自己的数据访问代码,并确保应用程序松散耦合。有人可以给我任何指导吗?
答案 0 :(得分:6)
我建议您对解决方案结构进行一些更改。
例如,项目的结构可以如下: -
这将是简单的POCO,代表您的域数据和任何服务的接口。这里没有业务逻辑。只是简单的属性。
例如。
公共类用户 { public int UserId {get;组; } public string Name {get;组; } }
- Core
\Entities <-- Poco's
\Services <-- Interfaces for services
这是您包含业务逻辑的地方。用户如何验证?我们如何计算订单何时应自动存档或其他什么?一般来说,我在这里不做任何数据库工作。
这是您执行基本数据库工作的地方。你说你没有使用L2S或EF等。没有probs。我会认真考虑使用Micro-ORM,例如Dapper或Massive。
你正在进行单元和集成测试,对吗?我建议xUnit或nUnit用于测试框架。
这是MVC3应用程序。我建议使用StructureMap进行依赖注入。 (您使用的是IoC / DI,对吗?)
您可能首先想到 - &gt;这是SOOO很多项目,对吗?好吧,很容易将它分成两个项目。
和核心库,服务,存储库都作为文件夹存在于Web应用程序项目中。
尝试而不是过度设计Visual Studio解决方案。大多数人认为他们需要大量的项目和抽象的抽象。因为这是他们认为其他人正在做的事情,这是正确的事情。好吧,那段思路是在2000年的早期......而且在2012年 - 从那时起,很多shiz都发生了变化。
尝试使用DI / IoJ,NuGet将这些库下载到您的解决方案中,使用Micro-OR / M进行数据访问和测试项目。
要检查的一些项目,重新:如何布局:
答案 1 :(得分:1)
也许,如果模型需要它。大多数模型都是具有公共属性的简单dtos。但你可以很容易地将其中的一部分封装起来。
不完全是。存储库是业务对象的集合。它可以从数据库创建这些对象的实例。
控制器是控制服务器上发生的事情的入口点。读取会将存储库中的数据加载到视图模型中,并将视图模型推送到视图中。写入将从存储库加载数据,更新域并保存更改。然后重定向到读取控制器操作。
您是否使用数据库或ORM无关紧要,您的存储库中具有相同的功能。
答案 2 :(得分:1)
我认为从小开始是好的,然后在需要时你开始扩大视野并开始根据需要分离出各层。如果您有2个模型,1个视图和一个表来在数据库中查询和更新,为什么要将您的工作分成20个项目。
从小处开始,让“需要”驱动设计。如果您需要在数据库中读/写大量表,现在可能是时候开始使用存储库模式了。 您发现现在需要至少10个或更多不同的模型,现在可能需要实施一个库来包含DTO /模型并将它们从Web应用程序中取出。
如果您要求编写单元测试或执行TDD,您会发现能够立即模拟存储库,业务和服务层就派上用场了。
虽然为了论证,我看到过类似于下面的项目(但大多数都不需要那个级别的分离):
其中大多数甚至被分解为单独的库,包含一个接口和另一个接口中的实现,依此类推。我参与过的一些项目有超过50个图书馆,如果不是所有的话,它们会分开,但总是基于要求或需要。
上述示例的想法是让Web应用程序仅处理将DTO传递给服务调用并从服务调用接收DTO。
您可以在大多数情况下使用DTO作为模型,但有时如果您需要基于多个DTO的平面模型,您可以创建自己的视图模型作为包装来展平多个DTO。
该服务在管理器中调用方法,并传递DTO,该DTO位于业务层库中。该管理器将使用DTO并将其映射到一个或多个实体,并调用存储库上传递这些实体的方法。存储库返回管理器用于构造要发送回的DTO的实体。
有很多方法可以做到这一点,我确信没有一种方法是唯一正确的方法。
您可以使用像Ninject这样的依赖注入框架来实现进一步的分离和独立性。
以上仅是一个例子。它对一群人来说可能很有用,而另一群人则认为这是不可接受的。这取决于很多因素,项目的规模是其中一个主要因素。
除此之外,总是从一个可管理的大小架构开始,随着需求的变化,你将不断重新考虑因素,无论是为了满足单元测试中的模拟,模型的数量已经变得无法管理。 Web应用程序或现在一个单独的团队必须编写服务层,并且您不希望这会干扰您的开发,现在服务层可能必须由不同的UI层使用,而不仅仅是您的Web前端等。 ...
答案 3 :(得分:0)
几点:
在您的存储库中拥有“业务逻辑”没有问题。事实上,你的大多数“商业逻辑”都将存在。您的存储库包含查询,如果这些查询完全有趣,那么这些查询将与您的“业务逻辑”密切相关。
在控制器中使用“业务逻辑”没有问题。您的控制器正在控制您的UI以及您的UI工作方式是“业务逻辑”。
根据定义,在分层体系结构中,每个层都知道它上面的层的公共接口。您的数据访问可以查看域层的公共接口。您的UI图层可以看到服务图层的公共界面。
如果您的项目非常小,您可以负担得起手工编码自己的数据访问层,而不是使用ORM或类似物,那么拥有完全解耦的Starship Enterprise架构可能只会让您的生活变得更加困难。 (并且由此我暗示我认为你疯狂编写自己的数据访问层 - 至少尝试像Dapper这样的轻量级框架。)
根据您的需求做出选择。问问自己“为什么X需要与Y分离”。 答案可能是“因此,当我进行单元测试时,我可以模拟X”。 答案可能是“所以我可以在我不需要了解Y的其他项目中使用X”。 如果你找不到答案,那就是YAGNI。