코드 마이그레이션 (읽기: 레거시 코드) 은 재미가 없습니다.이 작업을 완료하려면 엄청난 계획과 노력이 필요합니다.개발자에게 가장 흥미롭거나 동기를 부여하는 작업은 아니지만 레거시 코드를 새 라이브러리 버전으로 마이그레이션하려면 결단력과 적절한 경험이 필요합니다. 조다 타임 java.time으로의 마이그레이션은 세심한 계획과 실행이 필요한 마이그레이션 중 하나입니다.
Java 프로젝트가 Java SE 8 이전에 시작되었고 날짜/시간 처리를 사용한다면 아마도 SE 8 이전의 날짜 및 시간 함수를 처리하기 위한 훌륭한 라이브러리이자 사실상의 표준인 Joda-Time을 사용했을 것입니다.프로젝트를 사용하는 경우 여전히 Joda-Time을 사용하지만 java.time으로 마이그레이션한 다음 계속 읽고 싶습니다.
Java SE 8의 릴리스에는 일반적으로 java.time (JSR-310) 이라고 하는 새롭고 개선된 표준 날짜 및 시간 API가 포함되었습니다.조다-타임 프로젝트는 이제 java.time (JSR-310) 으로의 마이그레이션을 권장합니다.
java.time (JSR-310) 은 Joda-Time에서 많은 영감을 얻었지만 이전 버전과는 호환되지 않으며 개념과 용어가 변경되었습니다.그렇기 때문에 Joda-Time에서 java.time으로 마이그레이션하려면 변경하는 코드 한 줄 한 줄에 주의를 기울여야 합니다.이렇게 하려면 시간이 오래 걸릴 수 있으며, 더 쉽고 자동화된 마이그레이션 방법이 있었으면 하는 생각이 들 정도입니다.
마이그레이션할 수 있는 더 좋은 방법이 있습니다. Sensei를 사용하여 만들었습니다. Sensei는 사용자가 정의한 레시피 (규칙) 에 따라 코드 변환을 자동으로 수행하는 IntelliJ 플러그인입니다.반복적인 마이그레이션 작업을 수행하는 대신 재사용 가능한 레시피를 정의하는 데 시간을 할애하세요.자동화는 기존 Joda-Time 코드를 변환할 뿐만 아니라 팀이 새 코드를 작성할 때 IDE에 있는 지침을 따르는 데도 도움이 됩니다.
보다 빠르게 시작할 수 있도록 Sensei 공개 요리책을 만들었습니다. 자바타임에 대한 표준화 (JSR-310) 여기에는 덜 고통스러운 방식으로 Joda-Time에서 java.time으로 마이그레이션하는 레시피가 포함되어 있습니다.이 레시피는 계속 늘어나고 있으며 앞으로도 계속 확장하여 더 많은 레시피로 더 많은 적용 범위를 넓힐 예정입니다.
다음은 Sensei를 사용하여 어떻게 레거시 코드를 쉽게 마이그레이션할 수 있는지 확인하는 데 도움이 될 수 있는 샘플 마이그레이션의 예입니다.
반복적인 수동 마이그레이션부터 자동 코드 변환까지
한 줄의 코드를 Joda-Time에서 java.time으로 마이그레이션할 때 숨겨진 몇 가지 함정을 보여주는 새 DateTime을 만드는 예제를 살펴보겠습니다.그런 다음 java.time 표준화 (JSR-310) 쿡북의 Sensei 레시피 중 하나를 살펴보고 모든 개발자가 동일한 마이그레이션을 반복해서 재사용할 수 있도록 이 모든 정보를 캡처하는 방법을 살펴보겠습니다.
이 예제에서는 DateTime 필드의 값을 나타내는 7 int 인수로부터 Joda-Time DateTime을 구성합니다.
이것을 java.time에 상응하는 것으로 마이그레이션하는 방법은 무엇입니까?
더 이 생성자를 위한 조다 타임의 javadoc 말한다:
기본 시간대의 IsoChronology를 사용하여 날짜/시간 필드 값에서 인스턴스를 구성합니다.
처음에는 다음과 같이 가정할 수 있습니다. 날짜/시간 java.time에는 클래스가 있지만 클래스가 없습니다.구글에서 '조다 타임에서 자바 타임으로 마이그레이션하기'를 검색해 보면 스티븐 콜본의 블로그 게시물을 찾을 가능성이 높습니다. 조다 타임에서 자바 타임으로 변환.
이것은 여러분에게 좋은 출발점이자 java.Time.ZonedDateTime 또는 java.Time.OffsetDateTime을 사용하는 방향을 제시해 줍니다.첫 번째 질문은 다음과 같습니다. 어떤 것을 사용해야 할까요?아마도 스티븐의 의견에 따르면 ZonedDateTime인 것 같습니다.
올려다보는 존 데이트타임 자바독, 생성자를 전혀 볼 수 없습니다.Stephen의 블로그 글로 돌아가서 아래 내용을 더 읽어 보겠습니다.
건설.Joda-Time에는 Object를 받아 형식 변환을 수행하는 생성자가 있습니다. java.time에는 팩토리 메서드만 있으므로 문자열에 parse () 메서드가 제공되지만 변환은 사용자 문제가 됩니다.
따라서 정적 팩토리 메서드가 있어야 합니다. 정적 메서드를 검색하면 꽤 비슷해 보이지만 완전히 같지는 않습니다.
오리지널 Joda-Time DateTime 생성자와 같은 7개의 int 파라미터를 가지고 있지만, 주의를 기울이지 않으면 중요한 세부 사항을 놓치게 됩니다.7번째 파라미터는 더 이상 밀리초를 나타내지 않고 나노초를 대신 사용합니다. 이는 java.time이 Joda-Time보다 정밀도를 높여 나노초까지 순간을 측정하기 때문입니다.쉽게 놓칠 수 있는 중요한 세부 정보입니다.또한 이 메서드에는 zoneID가 필요하기 때문에 이전에는 왜 필요하지 않았는지, 지금은 왜 필요한지 궁금해집니다.
기본 시간대를 사용한다고 언급한 원래 생성자의 javadoc을 기억하고 있는데, 기본 ZoneId를 가져오는 방법이 있을까요?
더 ZoneID를 위한 자바독 나열된 생성자에 대해서는 알려주지 않지만 정적 메서드를 살펴보면 사용할 수 있습니다. 시스템 기본값 ()
이제 ZoneId를 정리했으니 밀리초에서 나노초로의 변환은 어떻게 해야 할까요?아마도 java.util.Concurrent.TimeUnit을 사용하여 변환을 수행할 수 있을지도 모릅니다.
이 메서드는 long을 반환하고 메서드는 int를 예상하므로 이제 해결해야 할 변환 문제도 있습니다.간단한 것을 시도해 볼 수도 있겠네요.곱셈?
이것은 작동하겠지만 약간 어색해 보입니다.아직 눈치채지 못하셨다면, 저희는 코드 한 줄을 마이그레이션하는 데 상당한 시간과 노력을 들였습니다.하지만 상상할 수 있듯이 이러한 편집 작업을 수작업으로 수행해야 하는 경우가 많지만 더 나아질 수는 없습니다.
하지만 java.time API를 좀 더 자세히 살펴보면 좀 더 유창해 보이는 솔루션을 찾을 수 있습니다.
ZonedDateTime에는 밀리초를 설정하는 명확한 방법이 없지만 다음을 사용하여 설정할 수 있습니다. with (임시 필드 필드, 긴 새 값) 메서드, 사용 크로노필드. 밀리_오브_초 템포럴 필드로.
그리고 자바 문서는 우리를 위해 나노초로의 변환을 수행할 것이라고 언급했습니다.
이 필드를 사용하여 값을 설정하는 경우 값에 1,000,000을 곱한 NANO_OF_SECOND를 설정하는 것과 같은 방식으로 동작해야 합니다.
따라서 팩토리 메서드에서 나노초에 대해 0을 지정하고 다음을 사용할 수 있습니다. 와 원래 값과 밀리초를 모두 포함하는 ZonedDateTime을 만드는 메서드입니다.
최종 결과를 보면 코드 한 줄만 변경한 것처럼 보입니다. 단 한 번의 마이그레이션을 조사하는 데 들인 노력을 제대로 보여주지 못합니다!
더 빠르고 쉽게 마이그레이션할 수 있는 레시피 만들기
Sensei는 어렵게 얻은 정보를 다른 개발자와 공유할 수 있는 방법을 제공합니다.이러한 모든 요구 사항을 담은 레시피를 만들면 Sensei 사용자는 마우스 클릭 한 번으로 이 마이그레이션을 수행할 수 있습니다.
Sensei 레시피는 세 가지 주요 섹션으로 구성됩니다.
이 호출을 해당 java.time으로 마이그레이션하는 데 도움이 되는 Sensei 레시피 (YAML 레시피로도 볼 수 있음) 를 살펴보겠습니다.
DateTime foo = 새 날짜 시간 (년, 월, 월, 일, 시, 분, 분, 분 단위, 밀리초)
메타데이터 섹션
메타데이터 섹션에는 레시피에 대한 정보와 사용 방법이 포함되어 있습니다.
검색 섹션
Sensei 레시피의 검색 섹션은 이 레시피를 적용해야 하는 코드 요소를 지정합니다.
검색:
인스턴스 생성:
인수:
1:
유형: 정수
2:
유형: 정수
3:
유형: 정수
4:
유형: 정수
5:
유형: 정수
6:
유형: 정수
7:
유형: 정수
목표 개수: 7
형식: org.joda.time.DateTime
이 검색 섹션에서 우리는 다음과 같은 것을 볼 수 있습니다:
- 검색 중 인스턴스 생성, 즉, 생성자의 사용.참고: 다음과 같은 것들이 있습니다. 다른 많은 검색 대상 사용 가능
- 생성자는 7개의 인수를 가져야 합니다. 이 인수는 다음과 같이 지정됩니다. 아그카운트 재산
- 인수 1-7은 int 유형이어야 합니다.
- 의 생성자를 찾고 있습니다. 유형 org.joda.time.DateTime
사용 가능한 수정 섹션
AvailableFixes 섹션에서는 일치하는 코드 요소에 적용할 수 있는 수정 사항을 하나 이상 지정할 수 있습니다.각 수정에는 여러 작업이 포함될 수 있으며, 이 경우에는 2개의 작업을 수행하는 단일 수정이 있습니다.
- 더 이름 수정 사항은 'Quickfix' 메뉴에서 사용자에게 표시되며 사용자가 이 퀵픽스를 적용하면 어떤 일이 발생하는지 설명합니다.
- 작업 목록에는 이 퀵픽스가 수행할 작업이 표시됩니다.
- 더 다시 작성하십시오 액션은 콧수염 템플릿을 사용하여 코드 요소를 다시 작성합니다.변수와 문자열 대체 함수를 사용할 수 있습니다.
- 더 할당된 변수 수정 액션은 이 생성자가 변수에 값을 할당하는 데 사용되고 있는지 확인합니다.그렇다면 이 작업을 수행하면 선언할 변수가 에서 지정한 유형으로 수정됩니다. 유형
레시피를 사용하여 코드 변환 수행
레시피가 작성되고 활성화되면 코드를 스캔하고 적용할 수 있는 세그먼트를 강조 표시합니다.
아래 스크린샷에서 Sensei가 대상 생성자를 표시한 것을 볼 수 있습니다.표시된 생성자 위로 마우스를 가져가면 레시피, 단축설명 및 Quickfix 옵션이 표시됩니다. Java.Time.ZoneDateTime으로 마이그레이션
우리가 선택한 후에 Java.Time.ZoneDateTime으로 마이그레이션 quickfix, 레시피에 지정한 작업에 따라 코드가 변환됩니다.
Sensei를 통한 일회성 마이그레이션 및 팀 전반의 통일된 코딩 관행
위의 예에서 볼 수 있듯이 한 줄의 코드를 마이그레이션하려면 힘들게 얻은 지식이 포함될 수 있습니다.Sensei는 이러한 지식을 팀 내에서 공유할 수 있는 실행 가능한 레시피나 요리책으로 전환할 수 있습니다.일회성 마이그레이션 스프린트를 계획하거나 Joda-Time 코드를 접했을 때 java.time으로 점진적으로 즉시 변환하는 접근 방식을 취할 수 있습니다.논리적 단계 또는 단계별로 마이그레이션을 수행하는 방법으로 레시피를 활성화/비활성화할 수 있으며, Sensei에서 스캔한 파일의 범위를 확장하거나 축소할 수도 있습니다. 이러한 유연성은 코드 마이그레이션의 복잡성을 줄여줍니다.
라이브러리 마이그레이션은 Sensei를 사용하여 프로젝트를 표준화할 수 있는 다양한 방법 중 하나에 불과합니다.풀 리퀘스트나 직접 코딩할 때 자주 접하는 안티패턴 또는 특정 수동 코드 변환이 있는지 언제든지 확인할 수 있습니다.다음과 같은 세트를 가지고 있다면 코딩 가이드라인 개발자들이 놓치는 경우가 많지만 가이드라인을 레시피로 변환하여 개발자가 승인된 코드 변환을 자신 있게 적용할 수 있습니다.
질문이 있으시면 언제든지 연락주세요!다음 주소에서 Slack에 참여하세요. sensei-scw.slack.com