我正在试图找出构建易于维护和可测试的架构的最佳方法.经历了几个项目之后,我看到了一些非常糟糕的架构,我想避免在我自己的项目中犯下未来的错误.
假设我正在构建一个相当复杂的三层应用程序,我想使用DDD.我的问题是,我应该在哪里放置我的业务逻辑?有人说它应该放在服务(服务层)中,这确实有意义.拥有一系列遵循单一责任原则的服务是有道理的.
但是,有些人说这是反模式,业务逻辑不应该在服务层实现.为什么是这样?
假设我们有IAuthenticationService一个带bool UsernameAvailable(string username)签名的方法.该方法将实现所有必需的逻辑以检查用户名是否可用.
根据"这是一个反模式"的人群,这里有什么问题?
我在想我是否真的需要一个服务层.
我正在使用spring + hibernate用于桌面摇摆应用程序,此时我有gui/swing layer-> service layer-> dao layer.我只将spring用于@Transactional支持和IOC注入
最佳实践说我必须编写一个服务来使用我的daos,并将所有事务管理放在服务中.
但我经常意识到,服务层只复制dao方法,例如:
// a DAO example
@Repository
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO {
public List<Customer> findAllCustomerILikeName(String name){
return getSession()
.createCriteria(Customer.class)
.add(Restriction.ilike("name", name))
.list();
}
}
// Customer service to use this dao...
@Service
@Transactional
public class CustomerService {
@Autowired
CustomerDAO customerDAO;
// Why i can't call DAO instead the service?
public List<Customer> getAllCustomersByName(String name){
return customerDAO.findAllCustomerILikeName(name);
}
}
Run Code Online (Sandbox Code Playgroud)
这是服务层的一个典型用法... Hibernate是db-agnostic,spring是技术不可知的:所以,我真的需要它吗?
如何管理所有DAO的独特服务类?我认为这可能是一个很好的妥协,或者,这是一种不好的做法?
我知道将@Transactional放在DAO上是一种糟糕的方式,但此时此刻我必须编写仅用于放置@Transactional的服务...
编辑
关于我的应用的更多信息.
我的应用程序是一个管理软件,管理用户注册,产品,订单和其他类似的东西.实际上它包含了很多读取实体 - >编辑 - >保存实体或创建 …
我正在开发一个分层的ASP.Net MVC 3 Web应用程序(EF 4.1):模型,存储库,服务,控制器,某些情况下的ViewModel和视图.
现在我的问题是最好的做法之一.需要访问另一个实体的实体服务类是否应使用其服务或其存储库.例如,假设实体A的服务方法需要在创建A时更新实体B. A的服务类应该使用B的存储库还是服务层?两者都有可能,但最佳做法是什么?就个人而言,我更喜欢一项服务来访问另一项服务.这样,它可以作为访问更多进化方法的说法.
我有一个API,我通过REST暴露,我正在考虑在哪里放置权限限制.
我已经读到有一个关于保护服务层的最佳实践,因为它正在进行工作,你不知道它将被调用到哪里但是我不确定什么是关于WS的最佳实践层.
我有一个想法是,我需要在服务层上有一个非常精细的授权模型和WS层上非常粗糙的授权模型,以便最大限度地减少破坏DRY原则,但仍然有一些概念深度防守.
例:
对于Users资源,有一个UserWS和一个UserService.管理员可以创建/更新/删除用户,用户可以阅读其他用户.
假设UserWS受到约束,%root%/users我将intercept-url为该URL 定义一个具有ROLE_USER权限的URL,该权限仅表示您必须是用户才能到达那里,但服务层本身将指定相关方法的特定权限.
其他选择是:
在服务和WS
-Pro 上放置相同的授权要求 - 您将尽早过滤掉入侵者(如果您使用的是弹簧mvc,则保存参数的转换)
配置的复制是维护问题并且容易出错=>安全问题
如果来自WS
Con的服务层可能会从不同的上下文中使用, 则仅将授权要求尽快放在WS -Pro-Filter上
仅在服务上实现授权要求 -
Pro-No Duplication
Con-Overhead允许"直率"无效请求到达服务层
非常感谢有关选项的任何反馈
我正在开发一个简单的Java应用程序,用于通过RESTful API对数据库进行CRUD操作.它分为三层:控制器层,服务层和DAO层.
通常,我为每个域对象创建一个服务接口.说,User:
public interface UserService {
List<User> getAll();
User create(User entity);
void update(User entity) throws Exception;
void delete(Long id) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
然后我在服务类中实现该接口:
public class UserServiceImpl implements UserService { ... }
Run Code Online (Sandbox Code Playgroud)
我认为这种方法有几个缺点:
UserService,尽管我只有该接口的一个具体实现我将创建一个所有服务都将实现的接口:
public interface CrudService<T> {
List<T> getAll();
T create(T entity);
void update(T entity) throws Exception;
void delete(Long id) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
所以我选择名称CrudService来传达该界面提供的功能.然后,我有一个具体的服务类,用类型参数实现该接口User:
public class UserService implements CrudService<User> { ... }
Run Code Online (Sandbox Code Playgroud)
这样我的服务就有了UserService我认为更干净,更易读的名字.
我正在尝试创建一个干净的服务层,服务层作用于一个或多个存储库,每个存储库都依赖于它自己的雄辩模型.
例如,我可能有:
ForumService
|
+-- PostRepo extends PostInterface
| |
| +-- Post (Eloquent)
|
+-- UserRepo extends UserInterface
|
+-- User (Eloquent)
Run Code Online (Sandbox Code Playgroud)
每个服务都通过定义它所需的依赖项ioc.所以,像:
// MessageService
// ..
public function __construct(UserInterface $userRepository,
MessageInterface $messageRepository) {
// ..
}
Run Code Online (Sandbox Code Playgroud)
我的存储库通过它们在各自服务提供商中的绑定来解决,例如:
class UserRepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app>bind(
'App\Models\Repositories\User\UserInterface',
'App\Models\Repositories\User\UserRepository');
}
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好.每个服务都获得它所需的存储库.
为了使服务层不受任何特定依赖性的影响,任何离开repo的东西都是一个简单的,不可变的数据对象.
日常用语的要点:
但是,我无法associate在服务或回购层为对方雄辩模型提出一个干净的模式.
鉴于Post模型有belongsTo(User::class)关系,我如何在Post存储库层干净地创建该关系.
我试过了:
public function associate($authorId)
{
$post->author()->associate($authorId);
}
Run Code Online (Sandbox Code Playgroud)
但是 …
人们如何设计服务层接口?
我正在编写一个大型Web应用程序(在PHP中),我们正在使用MVC,并编写精简控制器,例如(伪代码如下)
public savePersonAction() {
$input = filter($_GET);
... input validation ...
$result = $this->_service->savePerson( ? );
... etc
}
Run Code Online (Sandbox Code Playgroud)
应该在服务中的savePerson采用整个$ input结构或上下文的参数(在PHP中,是一个关联数组)?
这个 -
public function savePerson(array $input) {
Run Code Online (Sandbox Code Playgroud)
或者应该将所有输入字段分开并提供"硬"接口,例如
public function savePerson($title, $firstName, $lastName, $dateOfBirth, ... etc.. for many more) {
Run Code Online (Sandbox Code Playgroud)
谢谢.
保罗
php model-view-controller service web-applications service-layer
我仍然很难绕过这个.我想像我这样分开我的图层(dll):
1)MyProject.Web.dll - MVC Web App(控制器,模型(编辑/查看),视图)
2)MyProject.Services.dll - 服务层(业务逻辑)
3)MyProject.Repositories.dll - 存储库
4)MyProject. Domain.dll - POCO类
5)MyProject.Data.dll - EF4
工作流程:
1)控制器调用服务以获取对象以填充视图/编辑模型.
2)服务调用存储库来获取/持久化对象.
3)存储库调用EF以从SQL Server获取/持久化对象.
我的存储库返回IQueryable(Of T),在其中它们使用ObjectSet(Of T).
所以我看到这一点,图层完全依赖于下一层和包含POCO类的lib?
一些问题:
1)现在我的存储库与EF一起正常工作,它们将依赖于System.Data.Objects,现在我在我的存储库层与EF紧密耦合,那是不是很糟糕?
2)我正在使用UnitOfWork模式.那住哪儿?它有一个Property Context As ObjectContext,因此它也与EF紧密耦合.坏?
3)我如何使用DI使这更容易?
我希望这是一个松散耦合的测试.有什么建议?
----------编辑----------
如果我在这里正确的轨道,请告诉我.另外,因此服务器注入一个IRepository(Of Category)权限,它如何知道它与EFRepository(Of T)的具体类之间的区别?与UnitOfWork和服务相同?
一旦有人帮助我把它弄清楚到我所理解的地方,我知道它看起来似乎微不足道,但是男人,我有一个时间包围我的头!
调节器
Public Class CategoryController
Private _Service As Domain.Interfaces.IService
Public Sub New(ByVal Service As Domain.Interfaces.IService)
_Service = Service
End Sub
Function ListCategories() As ActionResult
Dim Model As New CategoryViewModel
Using UOW As New Repositories.EFUnitOfWork
Mapper.Map(Of Category, CategoryViewModel)(_Service.GetCategories)
End Using
Return …Run Code Online (Sandbox Code Playgroud) asp.net-mvc unit-of-work repository-pattern service-layer entity-framework-4
我在Internet上看到的WPF MVVM应用程序示例将VM视为与服务层交互的层,该服务层使用来自外部库的"旧"事件,或使用HTTP或其他任何方式与Web交互.但是如果我自己构建所有M,V,VM,服务和其他部分呢?如何正确构建服务层和viewmodel层之间的交互?我可以直接ObservableCollection<OrderModel>进入服务并从视图的视图模型返回它,或者它被认为是一种不好的方法,还有更好的选择吗?
以下是在CodeIgniter应用程序中实现服务层的两种方法.
1.send request to the controller
2.calling service layer methods from controller
3.return processed result data set(D1) from service layer to controller
4.then according to that data set controller demand data from model
5.model return data set(D2) to the controller
6.then controller send second data set(D2) to view.
Run Code Online (Sandbox Code Playgroud)
第二种方法
1.send request to the controller
2.calling service layer methods from controller
3.service layer demand data from model
4.model send requested data set(d1) to the service layer
5.after some processing return …Run Code Online (Sandbox Code Playgroud) service-layer ×10
java ×3
php ×2
.net ×1
asp.net-mvc ×1
c# ×1
codeigniter ×1
eloquent ×1
hibernate ×1
laravel ×1
layer ×1
mvvm ×1
oop ×1
repository ×1
service ×1
spring ×1
swing ×1
unit-of-work ×1