코드 마이그레이션 (읽기: 레거시 코드) 은 재미가 없습니다.이 작업을 완료하려면 엄청난 계획과 노력이 필요합니다.개발자에게 가장 흥미롭거나 동기를 부여하는 작업은 아니지만 레거시 코드를 새 라이브러리 버전으로 마이그레이션하려면 결단력과 적절한 경험이 필요합니다. 조다 타임 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