Java 및 Spring Boot을 사용하여 도메인 모델 빠르게 생성

17946 단어 springjava
개요
본고에서, 우리는 간단한 응용 프로그램을 위해 역 모델을 만들 것이다.응용 프로그램 업무 설명을 바탕으로 모델의 클래스/대상을 만드는 방법을 설명할 것입니다.우리는 실체가 모델의 일부분이라고 주장한다.
여기서 우리는 클라이언트-서버 체계 구조를 가진 웹 응용 프로그램의 도메인 모델링을 논의한다. 그 중에서 서버 쪽(백엔드)에 자바가 있다.모든 예는 Java 언어로 작성되었습니다.Spring Boot을 사용하여 애플리케이션 시작을 가속화합니다.
구현 시작
우리가 사용하는 도구:

  • Java 8 JDK from AdoptOpenJDKSdkMan을 함께 설치

  • SpringBoot- Spring Starter을 사용하여 통합 구축된 응용 프로그램을 신속하게 시작할 때만 사용

  • Maven- 내부적으로
  • 구축에 사용

  • JUnit- 게임 영역
  • 에 사용

  • Intellij Idea- 코드 편집(VS Code 또는 Sublime 사용 가능)
  • Windows 운영 체제를 사용하는 경우 Java JDK 8을 수동으로 설치하거나 Maven을 수동으로 설치할 수 있습니다.Spring Initializer-https://start.spring.io은 Spring Boot starter 응용 프로그램을 다운로드하는 데 사용할 수 있습니다.그러나 MAC OS와 Linux에서 가장 빠른 방법은 터미널 명령을 사용하는 것입니다. 보시다시피.
    응용 프로그램을 시작하고 실행하십시오.
    # install SDKMAN
    curl -s "https://get.sdkman.io" | bash
    # install JDK
    sdk install 8.0.212.j9-adpt
    # create app
    curl https://start.spring.io/starter.zip -d name=CindyKat -d groupId=com.colaru -d artifactIf=cindykat -d packageName=com.colaru.cindykat -d dependencies=web -d javaVersion=8 -o cindykat-springboot.zip
    # unzip, then run it
    unzip cindykat-springboot.zip -d cindykat-springboot
    cd cindykat-springboot && ./mvnw spring-boot:run
    
    현재, 우리의 응용 프로그램은 8080에서 시작되고 실행되었습니다. - 이것은 웹 응용 프로그램입니다!네트워크 응용 프로그램이 필요하지 않습니다. - 뭔가를 시작하고 실행할 수 있습니다.

    우리는 다음과 같은 프로젝트 구조를 가지고 있다.

    애플리케이션 도메인이란 무엇입니까?
    영역 모델은 우리 코드 중의 한 곳으로 여기서 우리는 응용 프로그램의 업무를 모델링한다.일반적으로 응용 프로그램 모델은 반드시 그 실현된 업무를 직접 반영해야 한다.우리의 코드는 반드시 우리가 모델링하고 있는 현실 이야기이어야 한다.우리는 프로젝트에 참여하는 모든 사람들이 사용할 수 있도록 보편적으로 존재하는 언어를 사용해야 한다.
    이것은 우리가 모델링하는 현실에서 가지고 있는 다른 추상적인 것을 도입할 필요가 없다.업무 중의 명사와 동사는 반드시 우리의 클래스, 필드와 방법의 명칭에 나타나야 한다.우리가 다른 것을 소개할 때, 우리는 과도한 공사로 의심받을 수도 있다.

    이미지 출처: https://www.slideshare.net/Dennis_Traub/dotnetcologne2013-ddd
    왜 모델이 이렇게 중요합니까?응용 프로그램의 모든 나머지 부분은 모델과 접촉하기 때문이다.그룹화/그룹화 취소의 복잡성 때문에 DTO 또는 WS-REST 리소스 또는 지속적인 솔리드의 개별 패키지를 보유하기 어렵습니다.만약 우리가 내부 모델을 시스템 밖으로 폭로하고 싶지 않다면, 우리는 어쩔 수 없이 이렇게 할 것이다.따라서 우리는 응용 프로그램의 모든 층에서 이 모델을 사용할 것이다.UI, 지속성, 보고서, WS, 메시지 전달 통합이 도메인 모델 클래스를 사용하고 있는지 확인할 수 있습니다.
    시간의 추이에 따라 모델은 더욱 복잡해질 수 있다(수백 개의 종류).모델의 내용은 끊임없이 발전하고 전체 응용 프로그램에 영향을 줄 것이다.이것은 새로 개발팀에 가입한 사람들이 어떤 응용 프로그램에서 가장 이해하기 어려운 부분이다.이것은 다른 응용 프로그램에서 다시 사용하는 라이브러리나 프레임워크가 아니라 업무에 특정한 것이다.업무가 매우 복잡할 수 있다.
    DDD 브로셔
    Java 웹 응용 프로그램을 시작하는 방법은 다음과 같습니다.
  • 백엔드 우선 순위 - 테스트를 사용하여 서버 사이드
  • 의 핵심적인 도메인 모델로 자바 도메인을 만듭니다.
    먼저
  • 프런트엔드 - HTML/CSS/JavaScript가 있는 사용자 체험/사용자 인터페이스부터 사용자 상호작용을 보여주는 실체 모델을 만듭니다. - JSON 또는 Typescript의 도메인 모델
  • 을 사용할 수 있습니다.
    일반적으로 한 팀은 전방에서 일하고, 다른 팀은 후방에서 일하며, 그들 간의 계약은 API 규범을 흔들거나 개방하는 것이다.
    첫 번째 방법은 분야를 모델링하는 것이다. 이것은 본고의 주제이다.아주 유명한 책의 주제이기도 하다. 엘릭 에반스의 Domain-Driven Design.이 책에서 본고에서 묘사한 도형 실체 외에 더 많은 주제를 소개하였다.

    사진 Domain Driven Design Quickly 서적
    어플리케이션 비즈니스 노트
    우리가 실현하고자 하는 응용 프로그램은 Google Trending Searches에 제공된 데이터에 대한 분석 시스템인 구글이 매일 보고하는 구글 검색 역사와 국가이다.Google Trends에서 데이터를 가져와 시스템에 저장하여 분석할 수 있도록 하고 다른 형식으로 표시하고자 합니다.

    이런 상황에서 분석 시스템에서 사용하는 영역을 모델링하는 것은 매우 간단할 것이다.검색 데이터를 가져오는 데 사용되는 형식과 실체를 구분하기 때문입니다.다음 Google Trends Atom 통합 형식 XML 세션을 참조하십시오.
            <item>
                <title>Women's World Cup 2019</title>
                <ht:approx_traffic>1,000,000+</ht:approx_traffic>
                <description>2019 Women, Women World Cup, WWC</description>
                <link>https://trends.google.com/trends/trendingsearches/daily?geo=US#Women's%20World%20Cup%202019</link>
                <pubDate>Mon, 10 Jun 2019 22:00:00 -0700</pubDate>
                <ht:picture>https://t2.gstatic.com/images?q=tbn:ANd9GcTW4UzPHNC9qjHRxBr6kCUEns71l8XK6HYcmLpJbhlfZWUbeBQPiia1GDzN3Ehl7nfD-HPbgnG_</ht:picture>
                <ht:picture_source>CBSSports.com</ht:picture_source>
                <ht:news_item>
                    <ht:news_item_title>&lt;b&gt;2019 Women&amp;#39;s World Cup&lt;/b&gt; scores, highlights: Canada squeaks by, Japan underwhelms, Argentina gets historic point</ht:news_item_title>
                    <ht:news_item_snippet>Day 4 of the &lt;b&gt;2019&lt;/b&gt; FIFA &lt;b&gt;Women&amp;#39;s World Cup&lt;/b&gt; in France featured a two-game slate with two potential contenders opening their campaigns against slightly inferior opponents. When the dust settled, neither team looked particularly sharp as only one goal was&amp;nbsp;...</ht:news_item_snippet>
                    <ht:news_item_url>https://www.cbssports.com/soccer/world-cup/news/2019-womens-world-cup-scores-highlights-canada-squeaks-by-japan-underwhelms-argentina-gets-historic-point/</ht:news_item_url>
                    <ht:news_item_source>CBSSports.com</ht:news_item_source>
                </ht:news_item>
                <ht:news_item>
                    <ht:news_item_title>&lt;b&gt;2019 Women&amp;#39;s World Cup&lt;/b&gt; scores, highlights, recap: Japan underwhelms in opener as Argentina gets historic point</ht:news_item_title>
                    <ht:news_item_snippet>Day 4 of the &lt;b&gt;2019 World Cup&lt;/b&gt; has a small slate of action with just two games, but two contenders to win the tournament were scheduled to play their opener. After the first match, we may just be talking about one contender. With talented Canada set to play&amp;nbsp;...</ht:news_item_snippet>
                    <ht:news_item_url>https://www.cbssports.com/soccer/world-cup/news/2019-womens-world-cup-scores-highlights-recap-japan-underwhelms-in-opener-as-argentina-gets-historic-point/</ht:news_item_url>
                    <ht:news_item_source>CBSSports.com</ht:news_item_source>
                </ht:news_item>
            </item>
    
    그래서 쉬워요!우리는 하나의 항목이 있는데, 그 중에는 뉴스 항목 목록이 있다.우리는 각각 하나의 원본 실체가 있는데, 그것은 뉴스 항목 사이에서 중용될 것이다.또한 프로젝트는 국가/지역이 필요합니다. 국가/언어를 지정하십시오.그게 다야.

    솔리드 맵 만들기
    우리 응용 프로그램에서 필드 모델은 단독 패키지가 될 것입니다.앞으로 다른 집합 (실체 그룹) 이 있을 수 있기 때문에, 뉴스피드라는 하위 영역 (전명 com.colaru.cindykat.domain.newsfeed) 을 만들어서 패키지를 명명합니다.
    도메인에 대한 완전한 모듈을 만드는 것이 가장 좋습니다. (다중 모듈 Maven/Gradle 프로젝트에서) 응용 프로그램의 다른 모듈에서 의존 관계를 만들 수 있기 때문입니다. 모든 다른 모듈은 도메인 모델을 사용합니다.
    먼저 IDE를 사용하여 기본 엔티티(DDDD 용어의 집합 루트)인 Item 클래스를 만들고 다른 클래스를 만듭니다.
    package com.colaru.cindykat.domain.newsfeed;
    
    import java.util.Date;
    import java.util.List;
    
    public class Item {
    
        private String title;
        private List<Tag> description;
        private String link;
        private String picture;
    
        private Date pubDate;
        private String pubDateAsString;
    
        private String approxTraffic;
        private Long approxTrafficAsNumber;
    
        private List<NewsItem> items;
        private Country country;
    
        // generate getters/setters using the IDE
    }
    
    
    
    public class NewsItem {
        private String title;
        private String snippet;
        private String url;
        private Source source;
    }
    
    
    public class NewsItem {
        private String title;
        private String snippet;
        private String url;
        private Source source;
    }
    
    public class Country {
        private String name;
        private String countryCode;
        private String languageCode;
        private String flag;
    }
    
    public class Source {
        private String name;
        private String url;
    }
    
    public class Tag {
        private String name;
    }
    
    마지막으로, 우리는 이 실체도를 얻을 것이다.

    이제 프로젝트 파일 시스템은 다음과 같습니다.

    빈혈역
    역의 흔한 문제는 Anemic Domain by Martin Fowler이라는 반모드-류는 상태만 있고 행위가 없다는 것이다.우리는 진실한 단어에서 동사가 아니라 명사만 얻는다.이런 상황에서 실체는 함수식 프로그래밍 언어의 데이터 구조이지 Uncle Bob is describing in this article의 실제 자바 대상이 아니다.이것은 매우 정상적이다. 왜냐하면 일반적으로 실체는 ORM의 지속적인 프레임워크에서 사용하는 데이터베이스 테이블의 맵이기 때문이다.
    우리는 동사가 역외 응용 프로그램의 서비스 층에 위치할 것을 희망한다.그러나 이런 상황에서 또 다른 토론이 시작되었다. 이 서비스가 지역의 일부입니까?
    그러나 실체에 직접 논리를 도입하는 것도 문제없다. 이런 상황에서 우리는 두 곳에서 업무 논리인 서비스와 지역 모델을 가질 것이라는 것을 깨달아야 한다.
    우리는 항목 실체 중의 일부 업무 방법 (일부 문자열에서 날짜, 그리고 문자열에서 긴 변환기) 을 소개할 것이다.
    public class Item {
            private Date pubDate;
        private String pubDateAsString;
        private String approxTraffic;
        private Long approxTrafficAsNumber;
    
        // other private fields
    
        public Date convertStringToDate(String pubDateAsString) throws ParseException {
            SimpleDateFormat parser = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z"); // Wed, 21 Dec 2016 13:00:00 +0200
            return parser.parse(pubDateAsString);
        }
    
        public Long convertStringToLong(String approxTraffic) {
            return new Long(approxTraffic.toString().replaceAll(",", "").replace("+", ""));
        }
    }
    
    테스트 영역
    도메인이 간단하더라도 JUnit을 사용하여 테스트를 시작하는 것이 좋습니다.우선, 우리는 Pom에 JUnit 라이브러리를 Maven 의존항의 일부로 포함해야 한다.xml:
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.2</version>
            <scope>test</scope>
        </dependency>
    
    이제 우리는 간단한 대상도를 사용하고 작은 기능을 검증하기 위한 첫 번째 테스트를 만들 수 있다.이것은 첫 번째 충분한 작업 프레임워크입니다. 테스트의 지도 아래 우리의 TDD 개발을 시작할 수 있습니다. 우리는 이 응용 프로그램에 다음 기능을 추가할 것입니다.
    class DomainModelTests {
    
        private Item item;
    
        @BeforeEach
        void setUp() throws ParseException {
            item = new Item();
            item.setTitle("Women's World Cup 2019");
    
            item.setLink("https://trends.google.com/trends/trendingsearches/daily?geo=US#Women's%20World%20Cup%202019");
            item.setPicture("https://t2.gstatic.com/images?q=tbn:ANd9GcTW4UzPHNC9qjHRxBr6kCUEns71l8XK6HYcmLpJbhlfZWUbeBQPiia1GDzN3Ehl7nfD-HPbgnG_");
    
            // tags
            Tag tag = new Tag();
            tag.setName("Word cup");
            List<Tag> tags = new ArrayList<>();
            tags.add(tag);
            item.setDescription(tags);
    
            NewsItem newsItem = new NewsItem();
            // source
            Source source = new Source();
            source.setName("USA TODAY");
            newsItem.setSource(source);
            newsItem.setTitle("&lt;b&gt;2019 Women&amp;#39;s World Cup&lt;/b&gt; scores, highlights: Canada squeaks by, Japan underwhelms, Argentina gets historic point");
            List<NewsItem> items = new ArrayList<>();
            items.add(newsItem);
            item.setItems(items);
        }
    
        @Test
        void buildNewItemTest()  {
            Assert.assertEquals(1, item.getItems().size());
            Assert.assertEquals(1, item.getDescription().size());
        }
    
        @Test
        void convertStringToLongTest() {
            String approxTraffic = "900,000+";
            item.setApproxTraffic(approxTraffic);
            item.setApproxTrafficAsNumber(item.convertStringToLong(approxTraffic));
            Assert.assertEquals(900000, item.getApproxTrafficAsNumber().longValue());
        }
    
        @Test
        void convertStringToDateTest() {
            String pubDateAsString = "Mon, 1 Jun 2020 09:00:00 -0700";
            item.setPubDateAsString(pubDateAsString);
            try {
                item.setPubDate(item.convertStringToDate(pubDateAsString));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            Calendar cal = new Calendar.Builder().setCalendarType("iso8601")
                    .setFields(YEAR, 2020, DAY_OF_MONTH, 1, MONTH, 5, HOUR, 18, MINUTE, 0, SECOND, 0)
                    .build();
    
            Assert.assertEquals(cal.getTime(), item.getPubDate());
        }
    }
    
    우리가 모든 테스트를 실행할 때, 줄은 녹색이다. (나는 먼저 테스트를 쓴 다음에 테스트 방법을 썼고, 테스트 실행에 실패했다. 나는 실현을 추가했다. 나는 다시 테스트를 실행했다. 지금은 통과했다).

    결론
    본고에서 우리는 작은 응용 프로그램에 간단한 모델을 만드는 방법을 소개했다.
    우리가 본 바와 같이 영역 모델은 응용 프로그램의 핵심 부분이다.분야 모델을 구성하는 이런 유형은 기술과 무관하다(병발성, 지속성은 현재 우리의 흥미에 부합되지 않는다)-업무의 현실만 묘사하고 프로젝트에서 사용하는 기술과 무관하다.
    Git 저장소
    GitHub에서 다음과 같은 출처를 발표했습니다.
    git clone https://github.com/colaru/cindykat-springboot.git
    cd cindykat-springboot
    mvn clean install // the tests will be executed successfully
    
    너는 그곳에서 나의 여정을 계속 기록할 수 있다.
    본문의 영감 링크
  • 값 대상과 실체: https://enterprisecraftsmanship.com/2016/01/11/entity-vs-value-object-the-ultimate-list-of-differences/
  • 빈혈역: https://martinfowler.com/bliki/AnemicDomainModel.html
  • 도메인 서비스: https://stackoverflow.com/questions/2268699/domain-driven-design-domain-service-application-service
  • 도메인 모델: https://martinfowler.com/eaaCatalog/domainModel.html
  • 서비스 계층: https://martinfowler.com/eaaCatalog/serviceLayer.html
  • 대상 및 데이터 구조: https://blog.cleancoder.com/uncle-bob/2019/06/16/ObjectsAndDataStructures.html
  • Eric Evans의 영역 구동 설계서: https://dddcommunity.org/book/evans_2003/
  • 분야 구동 설계 속성서: https://www.infoq.com/minibooks/domain-driven-design-quickly/#minibookDownload, /minibooks/domain-driven-design-quickly/#minibookDownload/
  • Bob 아저씨의 데이터 구조와 대상: https://blog.cleancoder.com/uncle-bob/2019/06/16/ObjectsAndDataStructures.html
  • 2019년 자바에 관한 10가지 신화: https://developer.okta.com/blog/2019/07/15/java-myths-2019
  • 어떤 Java SDK를 사용해야 하는지: https://developer.okta.com/blog/2019/01/16/which-java-sdk
  • 좋은 웹페이지 즐겨찾기