육각형 아키텍처

소프트웨어 구조의 발전 과정에서 loose coupling는 줄곧 중심적인 위치에 있었다.응용 프로그램을 구성 요소로 분해하는 데 중점을 두는데, 이 구성 요소들은 구성 요소에 의존하는 상황에서 전환하거나 교체하거나 업데이트할 수 있다.
육각형 체계 구조는 느슨한 결합 체계 구조의 또 다른 진보이다.그것은 분야로 전환하여 디자인을 구동하는 초기에 기원되었고 소프트웨어 디자인 분야의 진일보한 발전에 기반을 다졌다.

가져오기


육각형 체계 구조는 세 부분으로 나뉘는데 이 부분들이 응용 프로그램에서 맡은 엄격한 역할을 정의했다.

사용자 인터페이스
백엔드에는 많은 사용자 인터페이스가 있습니다. 모바일 응용 프로그램, 웹 응용 프로그램, 데스크톱 소프트웨어 등입니다. 업무 논리층에서 자원을 얻을 수 있습니다.
상업 논리
그것은 응용 프로그램의 핵심을 구성했다.그것의 목표는 사용자 인터페이스의 요구를 만족시키는 것이다.요청을 바탕으로 사용자 정의 논리를 실행하여 요청을 충족시키는 데 필요한 자원을 얻고 합의된 응답 형식으로 되돌려줍니다.
다음은 업무 논리층의 직책에 대한 작은 단어 구름이다.용례에 따라 책임이 다를 수 있다.

지원 서비스
이러한 서비스는 비즈니스 논리를 지원합니다.그것들은 모두 특정한 용도를 가지고 응용 프로그램에 데이터/서비스를 제공한다.그것들은 업무 논리층과 상호작용을 하여 두 층 간의 통신 계약을 유지하기만 하면 교체할 수 있다.예를 들면 다음과 같습니다.
  • 데이터 소스
  • 캐시 Redis
  • 등 서버
  • 알림 서비스
  • 결제 게이트웨이
  • 와 같은 추가 서비스
  • 마이크로 서비스 상하문에서 또 다른 마이크로 서비스.
  • 의도와 원칙


    응용 프로그램의 핵심이 다른 층과 통신하는 변화의 영향을 받지 않도록 하는 것이 목적이다.이 문제들은 우리의 육각형 경계에서 처리할 것이다.
    항구.
    포트는 우리의 핵심 응용 프로그램과 상호작용의 대상이다.외부에서 무슨 일이 발생하든지 간에 내부 응용 프로그램의 포트는 일치합니다.그것들은 내부 구성 요소가 무엇을 삽입했는지 모르는 상황에서 상호작용을 하는 인터페이스이다.
    어댑터
    포트는 정합성을 유지하지만 필요할 때 여러 응용 프로그램을 포트에 삽입할 수 있기를 희망합니다.이 프로그램들은 포트 정의의 인터페이스에 맞지 않을 수도 있습니다.이것이 바로 아웃 어댑터의 용무이다.그것들의 목적은 외부 응용 프로그램이 제공하는 데이터를 내부 응용 프로그램이 소화할 수 있는 형식으로 바꾸는 것이다.
    주의 - 간단하게 보기 위해서 육각형은 구조와 관련된 용어일 뿐이다.6 개의 포트가 있는 비즈니스 논리 계층으로 오해하지 마십시오.연결에 필요한 서비스에 따라 다각형은 더 많은 변이 있을 수 있다

    예.


    위의 그림에서 사용자 관련 작업을 처리하는 REST API의 작은 응용 프로그램을 상상해 보십시오.
    프런트엔드 포트 - 웹 사이트나 애플리케이션에서 요청할 수 있습니다.그것들은 서로 다른 매개 변수가 있을 수도 있고, 서로 다른 응답 형식을 기대할 수도 있다.우리는 모든 전방 참여자를 위해 어댑터를 만듭니다.
  • 요청 수신
  • 포트
  • 에 정의된 일관된 형식으로 변환
  • 내부 응용 프로그램에 전달합니다.
  • 내부 프로그램에 요청이 들어왔을 때, 포트가 공개한 인터페이스와 일치합니다.프로그램이 그것을 처리하고 포트가 원하는 형식으로 응답을 되돌려줍니다.
  • 포트는 요청을 받은 어댑터에 응답을 전달합니다.
  • 어댑터는 응답을 요청자에게 적합한 형식으로 변환합니다.
  • 데이터베이스 포트 - 내부 응용 프로그램은 요청을 충족시키기 위해 데이터베이스에서 데이터를 가져와야 한다.그것은 다시 한 번 일치하는 포트를 통해 상호작용을 한다.우리는 필요한 모든 데이터베이스를 이 포트에 삽입할 수 있다.실제 사용하는 데이터베이스는 실행할 때나 설정을 통해 결정됩니다.
    코드를 통해 데이터베이스 포트의 용례를 봅시다.

    코드 좀 보여 주세요.


    디자인 의도 - MySQL 데이터베이스를 시작하기를 원하지만, 미래에 다른 데이터베이스가 필요할지 모르겠습니다.우리의 코드는 필요할 때 데이터베이스를 쉽게 교환할 수 있도록 허용해야 한다.
    포트(커넥터)
    우리는 핵심을 위해 그것과 상호작용하는 인터페이스를 제공했다.인터페이스에서crud 조작을 실행합니다.
    public interface UserRepository {
        void save(User o);
        void delete(User o);
        void update(User o);
        User find(int id);
    }
    
    어댑터
    MySQL 데이터베이스 어댑터
    public class MySqlDatabaseRepository implements UserRepository {
        @Override
        public void save(User User) {
            System.out.println("Saving to database");
        }
    
        @Override
        public void delete(User User) {
            System.out.println("Deleting from database");
        }
    
        @Override
        public void update(User User) {
            System.out.println("Updating database");
        }
    
        @Override
        public User find(int id) {
            System.out.println("Finding in database");
            return null;
        }
    }
    
    데이터베이스와 상호 작용
    우리는 모든 통신이 인터페이스를 통해 이루어진다는 것을 이미 알고 있다.우리의 핵심 응용 프로그램은 UserRepository 인터페이스를 뛰어넘지 않을 것이다.
    우리의 핵심 서비스 중 하나를 봅시다.다음 과정은 사용자의 상세한 정보를 얻는 데 관한 것으로 기본일 수도 있고 완전할 수도 있다.
    public class UserDetailsClient {
    
        private UserRepository userRepository;
    
        public UserDetailsServiceImpl(UserRepository userRepository) {
            this.userRepository = userRepository;
        }
    
        public BasicDetails getBasicDetails(int id) {
            User user = userRepository.find(id);
            return new BasicDetails(user.getName(), user.getEmail());
        }
    
        public FullDetails getFullDetails(int id) {
            User user = userRepository.find(id);
            return new FullDetails(user.getName(), user.getEmail(), user.getAddress());
        }
    
    }
    
    그것이 어떻게 인터페이스 대상을 사용하는지 보고, 어떤 특정한 데이터베이스가 백엔드에서 일하는지 상관하지 않는다.
    그럼에도 불구하고 우리는 실제 실현을 서비스에 전달해야 한다.이 점을 해낼 수 있는 방법은 매우 많은데, 특히 현대의 틀 속에서는 그렇다.
    내가 여기서 사용하는 것은 constructor dependency injection 인데, 대부분의 인터페이스를 사용하는 대상 프로그래밍 언어에 적용된다.다른 모델은 공장 모델과 전략 모델일 수 있다.
    내 예에서 사용자의 상세한 정보를 얻으려는 외부는 전달에 필요한 어댑터를 통해 초기화됩니다. UserDetailsClient예컨대.
    UserDetailsClient userDetailsClient = new UserDetailsClient(new MySqlDatabaseRepository());
    userDetailsClient.getBasicDetails(userId);
    
    교환 데이터베이스
    시간이 지나자 신축성 때문에 노스QL 데이터베이스를 보유하는 것이 일을 더욱 쉽게 할 수 있다는 의견이 일치했다.이 경우 Mongodb 데이터베이스에 다른 어댑터를 도입하여 포트 정의 기능을 실현해야 한다.
    MongoDB 어댑터
    public class MongoDbRepository implements UserRepository {
        @Override
        public void save(User User) {
            System.out.println("Saving User to mongoDb");
        }
    
        @Override
        public void delete(User id) {
            System.out.println("Deleting User from mongoDb");
        }
    
        @Override
        public void update(User User) {
            System.out.println("Updating User in mongoDb");
        }
    
        @Override
        public User find(int id) {
            System.out.println("Finding User in mongoDb");
            return null;
        }
    }
    
    
    Mongodb 데이터베이스를 사용하려면 유일하게 변경해야 할 것은 UserDetailsClient의 초기화 방식이다.우리의 호출 코드는 다음과 같이 변경됩니다.
    UserDetailsClient userDetailsClient = new UserDetailsClient(new MongoDbRepository());
    userDetailsClient.getBasicDetails(userId);
    

    우세하다


  • 교환 가능한 구성 요소 - 데이터베이스 층에서 보듯이.같은 모델에도 다른 서비스가 있을 수 있다.예를 들어, 나는 알림 서비스를 제공하고 필요할 때 전자메일과 문자메시지 사이를 교환할 수 있다.

  • 업무 논리 분리 - 만약에 양호하게 실현된다면 외부에 변화가 발생할 때 육각형 체계 구조는 응용 프로그램의 핵심 업무 규칙에 위협이 되지 않는다.

  • 크로스 포트 테스트가 더욱 쉽습니다. 핵심 응용 프로그램의 테스트는 포트 주위에서 실행할 수 있습니다.필요하면 자신의 어댑터를 사용하여 아날로그 자원을 도입하여 데이터베이스가 없는 단원 테스트를 더욱 쉽게 할 수 있다.
  • 응용 프로그램의 체계 구조를 설계할 때 육각형 체계 구조는 명확하게 고려해야 할 것이 아니지만 현대 응용 프로그램, 특히 실현된 자바 세계가 아닌 인터페이스 인코딩을 둘러싼 자바 세계에 의외로 많이 사용된다.
    오늘날 사람들은 응용 프로그램의 설정 가능성과 적응성을 매우 중시한다.저차원 디자인 과정에서'포트와 어댑터 모델'을 기억하는 것이 고차원 디자인에서 더욱 중요하다.
    읽어주셔서 감사합니다.네가 이 문장을 좋아하길 바란다.평론에 어떤 칭찬과 건의를 남겨 주십시오.만약 네가 나와 연락하고 싶다면, 너는 인터넷에서 나를 찾을 수 있다
    흥미로운 사실: 코드 예시가 Github 조종사로 만들어져 인공적인 개입이 거의 필요 없다.

    좋은 웹페이지 즐겨찾기