2010-11-24 1 views
7

정말 서비스 레이어가 필요하다고 생각하고 있습니다.자바 스윙 애플리케이션 서비스 레이어

저는 데스크탑 스윙 응용 프로그램을 위해 스프링 + 최대 절전 모드를 사용하고 있으며 현재이 모드에서는 GUI/스윙 레이어 -> 서비스 레이어 -> DAO 레이어가 있습니다. @Transactional support와 IOC-injection에만 봄을 사용한다.

모범 사례는 내 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); 
} 

} 

이 서비스 층의 내 tipical 사용됩니다 ... Hibernate는 DB-불가지론 봄은 기술에 불가 지하다 : 그래서, 정말 필요합니까?

모든 DAO를 관리하는 고유 한 서비스 클래스는 무엇입니까 ?? 나는 이것이 좋은 타협이 될 수 있다고 생각하거나, 나쁜 습관입니까? 내가 DAO에 @Transactional을 넣어 알고

나쁜 방법이지만, 지금이 순간에 나는

편집 ... 만에 @Transactional을 넣어 약

더 많은 정보를 정기적으로 서비스를 작성해야 내 앱.

내 응용 프로그램은 관리 소프트웨어이며 사용자 등록, 제품, 주문 및 기타 항목을 관리합니다. 실제로 엔티티 -> 편집 -> 엔티티 저장 또는 작성 -> 편집 -> 저장 조작이 많이 포함되어 있으며, 최대 절전 모드로 인해 이러한 조작은 @manyto로 최대 절전 모드로 전환되므로 대부분 한 번에 의해 관리됩니다 ... collection과 cascade.save_update는 둘 이상의 엔티티를 동일한 지속 조작에 저장하도록 허용합니다. ,

public ItemFrame(){ 
// the constructor 
itemService=springAppContext.getBeans(ItemService.class); 
} 

public boolean validateForm(){ 
// test if the gui is correctly filled by user 
} 

public boolean save(){ 
// create an Item entity taking value from swing gui(JTextField etc) 
Item item=new Item(); 
item.setName(nameTextField.getText()); 
item.setEtc... 
// ItemService ' save method is a wrap around itemDao.save(item)... 
itemService.save(item); 
} 

private void saveItemActionPerformed(ActionEvent evt){ 
// When i press SAVE button 
if(validateForm()){ 
    save(); 
} 
} 

이 난 케이스의 대부분에있는 것입니다 : 내가 삽입, 편집 또는 항목을 만들 수있는

그래서, 예를 들어, 내 항목에 있습니다 (제품이 판매하는) JFrame의 그래서 나는 빈혈에 빠졌다고 생각합니다. 반 패턴 ...

고마워요.

+0

에 사용되는 후자를 허용 고려 correctly.Services entity.It 줘야 당이 있어야한다 나는 표준 패턴을 유지합니다. + DB가 변경되면 DAO 레이어를 다시 빌드합니다. + 1 btw –

+0

DB가 변경되면 서비스가 사용되지 않고 어떤 문제가 발생합니까? 나는 단지 DAO를 재건 할 것이고 모두 괜찮을 것이다. 그렇지 않은가? – blow

+0

여기서 주제를 조금 벗어나고 있습니다 만, ItemFrame 생성자에서 직접 콩을 컨테이너에서 가져 오는 이유는 무엇입니까? 컨테이너에서 주입 된 bean을 가져 오는 것보다이 접근법의 이점을 알 수는 없습니다. – prasopes

답변

3

서비스 계층이 dao를 복제하면 서비스 계층을 전혀 사용하지 않습니다. 나는 몇 가지 응용 프로그램에서 같은 실수를했다. "왜 서비스 레이어가 너무 못 생겨서 DAO가 중복 된 것인지 궁금해했다"...

서비스 레이어는 사용자의 어플리케이션을위한 인터페이스 여야합니다. 일부 방법은 DAO와 서비스에서 동일하지 않지만 주요 부분은 크게 다릅니다. 나는 나머지 코드를 보지 않고 이것을 말할 수는 없지만 질문 (몇 달 전에 내 질문과 거의 같다)에 의해, 나는 당신에게 anemic domain model antipattern을 사용하고있는 것처럼 보인다. 빈 도메인 모델에서 모델에는 필드 및 게터 만 포함되며 실제 객체 지향 원칙 (객체 == 데이터 + 동작)을 위반하는 실제 메소드 (비헤이비어)는 없습니다 ... 사용자의 동작은 서비스중인 트랜잭션 스크립트 계층에 있지만 모델 (도메인 계층)에 있어야합니다.

이 방법은 풍부한 도메인 모델 (@Configurable을 통해 모델링하기 위해 주입 된 bean)을 사용하는 것입니다. 이것은 레이어 패턴을 위반하고 아마도 당신이 옳을 것이라고 말할 수 있습니다. 그러나 우리는 응용 프로그램 (domain + dao + service)을 단일 구성 요소로 생각해야한다고 확신합니다 (Alistair Cockburn Hexagonal architecture/Ports and adapters 참조).

스윙 앱/웹 클라이언트는 핵심 구성 요소의 클라이언트가 될 것이므로 제한없이 데이터를 전환 할 수 있습니다 (데이터를 수정하는 모든 것이 코어에 있음).

그러나이 방법에는 제한/단점이 있습니다. 동등한 보안 (스프링 보안)이나 활성 레코드를 사용하여 최대 절전 모드를 사용한다면 엔터티에 접속할 때 DTO (엔터티 자체가 아닌)를 통해 모든 클라이언트와 통신해야합니다. 트랜잭션을 수행하고 데이터베이스를 수정할 수 있습니다 (보안 무시).

내가 아키텍처를 추측했으면 좋겠다. 그렇지 않다면 휠을 발명 한 것이 유감이지만이 게시물은이 사실을 알지 못하는 사람을 도울 수있다.

편집하여 편집에

: 심지어 간단한 CRUD 애플리케이션에서, 행동의 어떤 종류의 서비스 계층에 있어야합니다 - 예를 검증 (안 검증 "이 숫자는"하지만 일부 사업 특정 유효성 검사). 당신이 그것을 바꿀 경우, & 사본을 다시 붙여 넣기 때문에 이것은 당신의 견해에 있어야합니다. 코드를 살펴볼 때 "씬 클라이언트 (웹 브라우저에서보기)를 작성하기로 결정한 경우"라는 질문을해야합니다. 코드를 복사해야합니까? 대답이 YES 인 경우이 원격 호출에 대한 서비스 메소드를 작성해야합니다.

서비스 계층에서 할 수있는 또 다른 작업은 자동 작업입니다 (이 역할을 허용 한 사용자는이 항목을 삭제할 수 있음). 간단한 사용자는 자신의 항목을 편집 (삭제) 할 수 있어야하지만 다른 사용자는 삭제하지 않아야하므로 거의 모든 엔티티에 대해 서비스 계층이 있어야합니다. 그러나 역할 관리자의 사용자가이 작업을 수행 할 수 있습니다.

예제 코드 (내 응용 프로그램에서 문서 서비스 인터페이스의 일부 (봄 보안)) : 서비스 모두가 기사에 대한 자신의 의견을 절약 할 수 있습니다

@Secured("ROLE_EDITOR") 
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails); 

코멘트에서

....

그리고 마지막 주 : 당신은 아마도 당신이 서비스 레이어가 필요하다고 생각해야합니다. 좋은 방법으로 쓰여질 때, 앱은 융통성, 재사용 성 및 유지 보수성 측면에서 많은 이점을 얻을 것입니다. 그러나 그것을 작성하는 것은 꽤 힘들고 시간이 많이 걸립니다.당신은, 당신이 대신

ui -> service -> DAO 

집행의

+0

매우 감사드립니다, 내 첫 게시물에 대한 자세한 정보를 추가, 그것에 대해 의견을 남겨주세요! 고맙습니다! – blow

+0

내 엔티티는 getter 및 setter 만 포함하지만 내 daos는 CRUD보다 많은 메소드를 포함하므로 실제 저장소 (DDD, 구동 된 domanin 디자인에 따라)입니다. 내가 엔티티를 쓸 때 나는 항상 OO 방식으로 생각하려고 노력한다. 그래서 빈혈과 도메인 모델이 혼합되어 있습니다. – blow

+0

위대한 링크, 나는 파울러가 이것에 관한 기사를 가지고 있다는 것을 몰랐다. – prasopes

0

결국, 여러 DAO간에 동작을 조정해야합니다. 비즈니스 규칙에 약간의 복잡성이 생길 수도 있습니다 (예 : 특정 상태에있는 경우 [이]를 업데이트하지 마십시오). 여기서 서비스 레이어가 유용합니다.

그렇다면 "기술적으로"서비스 계층을 완전히 제거하는 데는 아무런 문제가 없습니다. 당신이 결국 당신이 필요하다고 결정할 때 조금 더 고통 스러울 것입니다.

1

어느 시점에서 응용 프로그램은 비즈니스 로직을 원할 것입니다. 또한 입력을 검증하여 악의적이거나 부적절한 요청이 없는지 확인할 수도 있습니다. 이 논리는 서비스 계층에 속합니다.

또한 DAO를 매우 일반적으로 만들 수 있으므로 많이 변경되지 않는 하나 또는 두 가지 방법 만 사용할 수 있습니다. 이렇게하면 앱의 기능을 추가/변경할 때마다 DAO 클래스에 심각한 오류가 발생할 위험이 줄어 듭니다.

DAO는 액세스 데이터 용입니다. 이 서비스는 비즈니스 논리를위한 것입니다. 그들을 분리 시키면 장기적으로 더 행복해질 것입니다.

0

:-) 그것없이 살 수있는 ((보기 구현) 변경 보안, 풍부한 도메인 모델, 이상의 인터페이스에서 전화)이이 모든 물건을 할 싶지 않는 경우 모든 작업을 위해, 모두

ui -> DAO 
ui -> service -> DAO 

당신이 그것을하고있는 나에게 따라 더 복잡한 작업