본 포스팅은 DroidKaigi 2017 ~ インスペクションとAndroid Lint Custome Ruleによる、単一責任実装の実践 을 기본으로 번역하여 작성했습니다
제 일본어 실력으로 인하여 오역이나 오타가 발생할 수 있습니다.
실제 슬라이드의 일본어
부분을 번역했다는 점 양해바랍니다.
Inspection 및 Android Lint Custome Rule에 따른 단일 책임 원칙의 실천
TDD 및 DDD가 시끄러운 요즘, 코드 구현의 단일 책임의 원칙 (SRP) 의역 ⇒ 단순화
가 요구되고 있습니다.
Android 앱 개발도 성숙기가 되고, 신 Activity의 반성에서 역할(책임)마다 클래스를 분할하고 소스 코드의 유지 보수 및 테스트 용이성 향상에 대한 관심이 높아지고 있지요.
Android Studio에는 Inspection이라는 강력한 소스 분석 (지적) 기능이 있다는 것을 알고 있을 것입니다.
문제점이 있는 부분을 편집기에서 하이라이트 표시하거나
“Analyze”메뉴의 “Inspect Code…“로 지적 목록을 “Inspection Results 도구 창”에서 카테고리별로 나열도 해주는 기능입니다.
이 “Inspection Results” 왼쪽 창에 있는 카테고리에 “Android > Lint > Correctness” 등, Android Lint 검사 항목이 반영되어있음을 알고 있는 사람도 많지 않을까요.
Android Studio의 Inspection에는 Android Lint도 이용되고 있습니다.
Android Lint는 독자적인 Custom Rule을 만들 수 있습니다.
그리고 Custom Rule을 만들기 위해 Java 소스 코드의 정적 분석 기반도 제공되고 있습니다.
이 세션에서는 단일 책임이 되는 간단한 구현을 강제 (강요)하는 오리지널 Android Lint Custome Rule 생성 및 이용에 대해 발표합니다.
초급자 ~ 중급자
cch-robo/Android_Lint_SRP_Practice_Example https://github.com/cch-robo/Android_Lint_SRP_Practice_Example
본 세션에서 사용하는 단일 책임이 되는 간단한 구현의 강제 (강요)를 촉구하는 오리지널 Android Lint Custome Rule 프로젝트입니다.
필드 변수(상태)를 변경하는 메소드가 복수 존재 (복합 책무)하는 경우, 그 공유 정도에서 책임(역할)의 혼재의 종류와 문제를 보고합니다.
주의
: 샘플 프로젝트에서는, Java 소스 탐색에 JavaPsiScanner, Java 소스 분석에 JavaElementVisitor를 사용하도록 다음과 같은 제한 사항이 있습니다.
단일 책임의 원칙
단일 책임의 원칙 또는 단일 책임의 원칙 (SRP : Single Responsibillity Principle)은 “클래스의 책무 (변경의 원인이 되는 것⇒역할)은 오직 하나이어야 한다.”…라는 원칙입니다.
다른 말로는 “클래스가 관리하는 상태 (책무 변경되는 것)은 복수 있어서는 안 된다.”…라는 것입니다.
하나의 상태는 복수의 요소로 구성되더라도 상관없습니다.
서적 「Clean Code 애자일 소프트웨어 전문가의 기술」 제10장 클래스에서는 다음과 같은 언급이 있습니다.
단일 책임의 원칙은 클래스를 “책임을 제한하고 작은 것으로 하는 것“… 아주 간단하지만 사람들이 말하는 神Activity가 생기는 것은 왜일까요.
나는 “A가 ㄱ일 때는 1, A가 ㄴ일 때는 2, 하지만 A가 ㄱ이고 B가 ㄷ일때는 3”… 등
요구 사양 자체가 흐름 절차형이 된 것
… 이 요인의 하나라고 생각합니다.
설계 공정이 적은 경우, 요구 사양 자체가 흐름 절차형이 되어있다고 작은 책임 클래스로 분할하는 설계 시간이 없으므로,
…처럼 보입니다.
요구 사양 자체가 흐름 절차형이 되어도 단일 책임의 원칙을 지키도록 하려면 “무엇이 무엇에 대해, 메시지를 보내는가“라는 객체지향 프로그래밍의 원점에서 자문하면서 프로그램을 할 것입니다.
흐름 절차 주체로부터 객체가 주체가 되도록 관점을 바꾸는 것
…라고 생각합니다.
엔터프라이즈 시스템 개발은 예전에 Transaction Script 패턴과 Domain Model 패턴의 논란이 있었습니다.
이전 페이지의 단일 책임이 깨진 요인이 이 논란과 겹친다고 생각해서 여기에서 언급하겠습니다.
Android Lint Custom rule 작성의 기초
샘플은 Android Studio Project Site의 다음 페이지의 기초 지식을 바탕으로 만들고 있습니다.
샘플 프로젝트는 다음 페이지의 소스 코드 내용을 참고로 하고 있습니다.
개발 버전의 소스를 참고하고 있는 것에 주의
lint의 사용법에 대한 설명 페이지
Android Studio로 Lint Custom rule을 개발한다
Lint Custom rule은 Java 응용 프로그램입니다. 따라서 다음과 같은 방법을 이용합니다.
일차 자료의 Writing Custom Lint Rules는 이쪽에 소개되어 있습니다.
샘플 프로젝트에서는 이쪽을 이용했습니다.
참고
: Activity는 만들지 않도록 합니다.-
아이콘으로 삭제합니다.주의
: 이전 단계는 논리 삭제이므로 app 모듈의 실제 디렉터리는 남아 있기 때문이다.(구체적인 내용은 후술)
apply plugin: 'java'
repositories {
jcenter()
maven {
url "http://dl.bintray.com/android/android-tools"
}
}
dependencies {
compile 'com.android.tools.lint:lint-api:25.3.0'
compile 'com.android.tools.lint:lint-checks:25.3.0'
testCompile 'junit:junit:4.11'
testCompile 'com.android.tools.lint:lint:25.3.0'
testCompile 'com.android.tools.lint:lint-tests:25.3.0'
testCompile 'com.android.tools:testutils:25.3.0'
}
// jar 파일 이름과 Lint-Registry는 자신에게 맞게 변경하세요
jar {
archiveName 'lint-example.jar'
manifest {
attributes("Lint-Registry":
"com.example.ExampleIssueRegistry")
}
}
defaultTasks 'assemble'
개발 쉽도록 Lint 라이브러리에 소스를 첨부해 봅니다.
샘플 프로젝트에서 사용하는 Lint Custom rule 관련 라이브러리(jar) 목록
lint-25.3.0.jar | Lint 도구 관련 |
lint-api-25.3.0.jar | Lint API 관련 |
lint-checks-25.3.0.jar | 기존 Detector 관련 |
lint-test-25.3.0.jar | 기존 Detector 테스트 관련 |
lombok-ast-0.2.3.jar | lombok AST 관련 |
uast-162.2228.14.jar | com.intellij AST (PSI) 관련 |
다운로드 원래 저장소에는 각 라이브러리의 소스도 배치되어 있습니다.
저장소에 있던 각 라이브러리 소스
lint | lint-25.3.0-sources.jar |
lint-api | lint-api-25.3.0-sources.jar |
lint-checks | lint-checks-25.3.0-sources.jar |
lint-test | lint-test-25.3.0-sources.jar |
lombok-ast | lombok-ast-0.2.3-sources.jar |
uast | uast-162.2228.14-sources.jar |
샘플 프로젝트 supplementary 폴더에 이전 페이지에서 소개한 소스 jar를 놓아두었습니다. 괜찮으시면, 이용해주세요.
lint-tests와 uast 기존 Detector 테스트 및 com.intellij 패키지의 소스가 누락
되어 있습니다.
Android Studio를 사용한 개발은 Terminal에서 gradlew 명령을 사용하여 빌드합니다.
$ ./gradlew clean ⇒ 빌드 결과를 클리어
$ ./gradlew test ⇒ 빌드 및 테스트를 실행
$ ./gradlew assemble ⇒ 빌드 및 jar 파일 만들기
Android Studio 메뉴의 Build 및 Run은 이용하지 않습니다.
Android Lint에서 Java 소스 분석의 기본
Android Lint에서는 Detector라고 부르는 Issue 검출기를 만들어 프로그램에 문제가 없는지 확인합니다.
Java 소스 구문 분석의 노드는 Java 언어의 언어 요소를 나타낸 것입니다.
구문 분석된 소스 노드 구조 예
Lint Custom rule 개발에 있어서 Java 소스 분석은 각 노드의 부모 관계와 중첩에서 구문 내용을 파악할 수 있습니다.
…를 사전에 파악 (학습) 할 필요가 있습니다.
샘플 프로젝트에서는, Java 소스의 구문 분석 결과의 트리 구조 (노드의 중첩 구조) 학습과 확인을 위해 PsiClassStructureDetector
을 준비했습니다.
PsiClassStructureDetector 사용
PsiClassStructureDetectorTest
에 샘플을 따라 디버그 출력하고자 하는 구문의 가상 Java 소스를 확인하는 테스트 메소드를 추가$ ./gradlew test
build/test-results/binary/
TEST-… PsiClassStructureDetectorTest.xml 확인
checkProject가 두번 실행되는
것에 주의
디버깅 출력 포맷
beforeCheckProject (Ph.1)<<<
beforeCheckFile (Ph.1) -> Source=>>>
*** 체크하는 파일의 원본 내용 ***
<<<
*** Node 디버깅 출력 포맷 ***
afterCheckFile (Ph.1) -> Source=>>>
*** 체크 한 파일의 소스 내용 ***
<<<
afterCheckProject (Ph.1)<<<
Node 디버깅 출력 포맷
Node=Node 이름
NodeImpl=Node 실제 이름
Source=>>> Node 텍스트 <<<
parent=>>> 부모 Node 텍스트 <<< : 부모 Node 실태 이름
children=>>> [Node 텍스트 : 자식 Node 실태 이름, Node 텍스트 : 자식 Node 실태 이름 ...] <<<
Node 디버그 출력 예
Node=PsiReferenceExpression
NodeImpl=EcjPsiReferenceExpression
Source=>>>isSuccess<<<
parent=>>>
if (isSuccess) {
message = "success";
}
<<<:EcjPsiIfStatement
children=>>>[isSuccess:EcjPsiIdentifier,
]<<<
예를 들어, if 문을 나타내는 PsiIfStatement에는
…이 준비되어 있습니다.
이 문서는 제공되지 않기 때문에, 노드가 제공하는 메서드를 찾아서 확인할 수 있습니다.
lint-checks/co.kr/android/tools/lint/checks
기존 Detector 소스에서 다양하게 배울 수 있습니다.
// JavaPsiScanner를 구현 한 Detector
ApiDetector.java, IconDetector.java,
RtlDetector.java, SdCardDetector.java
SecurityDetector.java, SupportAnnotationDetector.java,
UnusedResourceDetector.java, ViewHolderDetector.java
WrongImportDetector.java
Java 소스 분석을 위해, 구문 분석된 각종 노드를 제공받기에는 다음 단계를 밟습니다.
독자 Detector
클래스를 작성독자 AST Visitor
클래스를 작성독자 AST Visitor
의 인스턴스를 반환하도록 구현. 구문 분석된 노드를 제공받을 수 있도록 한다.독자 AST Visitor
의 각 노드 종별 visit 메소드로 제공된 노드를 수령
구체적인 구현의 흐름은 다음 장 Lint Custom rule 작성의 기본 흐름과 샘플 프로젝트의 소스를 확인해주십시오.
다음 단계로는 사전에 학습 한 특정 구문 트리 구조의 지식과 부모 노드에서 특정 자식 노드의 취득 방법에 대한 지식으로 제공된 노드의 중첩보다 Java 소스의 내용을 파악하여 생각되는 문제가 없는지 확인합니다.
Lint에서 문제가 되는 구문 구조를 지적하려면 문제가 되는 구문 구조를 상정하고 있어야 합니다.
조건부 성립의 처리 함수
로 나눠야 합니다.상기의 문제가 되는 구문 구조
는 단순하게 생각하면 다음과 같이 될 것입니다.
여기까지 상정되면 문제가 되는 소스의 트리 구조를 디버깅 출력하고 폭넓게 대처할 수 있도록 문제 구문 구조를 추상화하여 트라이&에러로 프로그램을 해나가면, Detector를 만들 수 있다고 생각합니다.
Java 소스 분석 프로그램 개발은 꾸준한 노력과 작업의 반복입니다.
샘플 프로젝트의 소스 분석 로직의 자세한 내용은 시간 일정과 소스를 보시면 알기 때문에 여기에서는 생략하겠습니다.
특징적인 것은 변수가 지역 변수인지 여부를 확인하기 위해 ElementUtil.ScopeBacktrack.seek()로 메소드 내에서 백트럭하는 것 정도입니다.
논리의 개요는
Issue 보고 (아래)를 실시한다.
책임 혼합
: 변경 상태 요소가 타인과 과부족이 있다… 라는 단순한 것입니다.
제한 사항
구문의 트리 구조를 배우고도 언급했지만, 테스트로는 checkProject ⇒ 노드 스캔(스캔)이 2회 실시하고 있습니다.
첫 번째와 두 번째는 노드 구성에 차이가 있습니다.
구체적으로는,
PsiParenthesizedExpression
)로 대체, 공백 (WhiteSpace
)이 추가되기도 합니다.Detector 테스트를 통과하려면 양자 모두에 대응하지 않으면 안됩니다.
샘플 프로젝트 supplementary 폴더에 1번째 checkProject_loop1.txt와 두 번째 checkProject_loop2.txt
디버깅 출력 내용의 파일을 넣어 두었습니다.
괜찮으시면, diff로 차이를 확인하시기 바랍니다.
두 번 실행 이유
Lint 테스트시의 메시지로부터
The lint check produced different results when run on the normal test files and a version where parentheses and whitespace tokens have been inserted everywhere.
The lint check should be resilient towards these kinds of differences (since in the IDE, PSI will include both types of nodes.
Your detector should call
LintUtils.skipParenthes(parent) to jump across parentheses nodes when checking parents, and there are similar methods in LintUtils to skip across whitespace siblings.
노드 검사는 반복하도록 요구할 수 있습니다.
Java 소스를 해석할 Lint Custom rule 작성의 기본 흐름
샘플 프로젝트의 소스 코드도 함께 확인하시기 바랍니다.
사용자 정의 규칙 Issue 감지 클래스는 Detector를 상속하고 Java 소스를 분석하기 위해 JavaPsiScanner을 구현합니다.
// Detector는、
// com.android.tools.lint.detector.api 패키지의 클래스
public class ExampleDetector extends Detector implements Detector.JavaPsiScanner {
… 생략
}
이전 페이지 문제 감지 Detector 클래스 내부에서 보고하는 문제 정보 Issue 인스턴스를 생성합니다.
// Issue, Category, Severity, Implementation, Scope, 는、
// com.android.tools.lint.detector.api 패키지 클래스입니다.
public static final Issue EXAMPLE_ISSUE = Issue.create(
"MixedWriteFieldsClassification", // Issue ID 문자열
"변경의~책무 혼합 문제", // Issue 문제 설명 표제
"변경하는~합니다。", // Issue 문제 대처 설명
Category.CORRECTNESS, // Issue 카테고리
4, // 심각도 (경:1〜10:중)
Severity.WARNING, // Issue 보고 심각 유형
new Implementation( // Detector과의 매핑
ExampleDetector.class, // 문제 검출 Detector
Scope.JAVA_FILE_SCOPE)); // 검출 대상 범위(복수 가능)
… 생략
// 프로젝트 검사의 전후 처리가 필요한 경우는 다음을 재정의
@Override
public void beforeCheckProject(Context context) { … }
@Override
public void afterCheckProject(Context context) { … }
// 각 Java 소스・파일 스캔 (AST Node visit)의 전후에
// 처리가 필요한 경우는 다음을 재정의
@Override
public void beforeCheckFile(Context context) { … }
@Override
public void afterCheckFile(Context context) { … }
… 생략 // Context ⇒ com.android.tools.lint.detector.api
createPsiVisitor() 메소드를 오버라이드하여 Java 소스 분석의 자체 AST Visitor 인스턴스를 지정합니다.
… 생략
// JavaElementVisitor ⇒ com.intellij.psi 패키지
// JavaContext ⇒ com.android.tools.lint.detector.api
@Override
public JavaElementVisitor createPsiVisitor(@NonNull JavaContext context) {
return new JavaElementExampleVisitor(context);
}
… 생략
getApplicablePsiTypes()을 오버라이드하여 분석 대상으로하는 AST (추상 구문 트리) 노드를 지정합니다
… 생략
// AST 노드의 PsiElement, PsiClass, PsiMethod는
// com.intellij.psi 패키지의 클래스
@Override
public List<Class<? extends PsiElement>> getApplicablePsiTypes() {
return Arrays.asList(
PsiClass.class,
PsiMethod.class);
}
… 생략
private static class JavaElementExampleVisitor extends JavaElementVisitor {
private final JavaContext mContext;
private JavaElementWalkVisitor(JavaContext context) {
mContext = context;
… 생략
}
// getApplicablePsiTypes()에서 지정한 AST 노드의 처리처
// 분석 visit 노드・엔트리에 대한 메소드를 오버라이드하여
// 인수 AST 노드를 분석하고 문제를 발견하는 과정을 구현합니다.
@Override
public void visitClass(PsiClass aClass) { … }
@Override
public void visitMethod(PsiMethod method) { … }
… 생략
}
전장 Android Lint에서 Java 소스 분석의 기초를 참조해주십시오.
// 문제가 발견된 AST 노드로부터 Java 소스의 해당 부분을 특정하여
// Issue 보고서를 발행 (보고) 합니다.
private void myReport(@NonNull PsiElement detected) {
// Java 소스의 문제 검출 위치를 특정
// Location은 com.android.tools.lint.detector.api 의 ㅡㄹ래스
String contents = mContext.getJavaFile().getText();
int startOffset = detected.getTextRange().getStartOffset();
int endOffset = detected.getTextRange().getEndOffset();
Location location = createLocation(mContext.file, contents, startOffset, endOffset);
// Issue로 보고하는 메시지 내용을 작성
String message = "메소드가~추천합니다";
// Issue 보고서를 발행
mContext.report(EXAMPLE_ISSUE, location, message);
}
private Location createLocation(
@NonNull File file, @NonNull String contents,
int startOffset, int endOffset) {
DefaultPosition startPosition =
new DefaultPosition(
getLineNumber(contents, startOffset),
getColumnNumber(contents, startOffset),
startOffset);
DefaultPosition endPosition =
new DefaultPosition(
getLineNumber(contents, endOffset),
getColumnNumber(contents, endOffset),
endOffset);
return Location.create(
mContext.file, startPosition, endPosition);
}
private int getLineNumber(
@NonNull String contents, int offset) {
// this li1ne number is 0 base.
String preContents = contents.substring(0, offset);
String remContents = preContents.replaceAll("\n", "");
return preContents.length() - remContents.length();
}
private int getColumnNumber(
@NonNull String contents, int offset) {
// this column number is 0 base.
String preContents = contents.substring(0, offset);
String[] preLines = preContents.split("\n");
int lastIndex = preLines.length -1;
return preContents.endsWith("\n")
? 0
: preLines[lastIndex].length();
}
Issue를 감지 Detector 할 수 있으면, 동작 확인을 해 봅니다.
LintDetectorTest를 상속하여 Detector 테스트・클래스를 만듭니다.
// LintDetectorTest 은
// com.android.tools.lint.checks.infrastructure 패키지의 클래스
public class ExampleDetectorTest extends LintDetectorTest {
… 생략
}
LintDetectorTest 추상 메소드 getDetector()를 구현하여 테스트 할 Detector를 지정합니다.
private Set<Issue> mEnabled = new HashSet<Issue>();
protected ExampleDetectorTest getDetector() {
return new ExampleDetectorTest();
}
… 생략
테스트 클래스 구성 주위의 구현의 참고 표
googlesamples / android-custom-lint-rules
getIssues()를 오버라이드하여 테스트 대상의 Issue를 지정합니다.
… 생략
@Override
protected List<Issue> getIssues() {
return Arrays.asList(ExampleDetector.EXAMPLE_ISSUE);
}
… 생략
// 다음 페이지의
// TestConfiguration 은 LintDetectorTest 의 서브 클래스
// LintClient ⇒ com.android.tools.lint.client.api
// Issue, Project ⇒ com.android.tools.lint.detector.api
getConfiguration()를 오버라이드하여 테스트 대상 Issue 만 테스트하도록 지정합니다.
… 생략
@Override
protected TestConfiguration getConfiguration(
LintClient client, Project project) {
return new TestConfiguration(client, project, null) {
@Override
public boolean isEnabled(@NonNull Issue issue) {
return super.isEnabled(issue)
&& mEnabled.contains(issue);
}
};
}
… 생략
public void testNoIssueClass() throws Exception {
mEnabled.clear();
mEnabled.addAll(Arrays.asList(
ExampleDetector.EXAMPLE_ISSUE));
String expected = "No warnings."; // 경고없음을 지정
String result = lintProject(
java( // 분석할 Java 소스의 가상 파일 경로
"src/test/pkg/NoIssueClass.java",
// 분석할 Java 소스의 코드・텍스트
"" + "package test.pkz;\n"
+ "public class NoIssueClass {\n"
… 생략
+ "}\n"
)
);
assertEquals(expected, result);
}
public void testExistIssueClass() throws Exception {
mEnabled.clear();
mEnabled.addAll(Arrays.asList(
ExampleDetector.EXAMPLE_ISSUE));
// 감지 소스 위치 (행과 위치) 및 오류 수와 경고 수까지 지정합니다.
String expected = "" // 상정하고 있는 경고 메시지를 지정
+ "src/test/pkg/ExistIssueClass.java:18: Warning: "
… 경고 메시지 생략
+ " public void greet() {\n"
+ " ~~~~~\n"
+ "0 errors, 1 warnings\n";
String result = lintProject(
java( … 생략 … )
);
assertEquals(expected, result);
}
Android Studio의 Terminal에서 다음 gradle 명령을 사용하여 테스트를 실행합니다.
$ ./gradlew clean
$ ./gradlew test
테스트 결과는 XML 형식으로 아래에 출력됩니다. build/test-results/binary/
테스트가 성공하면, 작성한 Issue를 저장할 수 있도록 합니다.
IssueRegistry를 상속하여 Issue 저장소 클래스를 만듭니다.
// IssueRegistry는 com.android.tools.lint.detector.api의 클래스
public class ExampleIssueRegistry extends IssueRegistry {
// getIssues()를 오버라이드하여 보관할 Issue를 지정합니다.
// (주) Issue로부터 Detector도 결정됩니다!
@Override
public List<Issue> getIssues() {
return Arrays.asList(
ExampleDetector.EXAMPLE_ISSUE); // 복수 지정 가능
}
}
// Jar Task로 만들 Android Lint에 대한 속성을 설정하여
// 독자 Lint 사용자 정의・규칙 Jar 파일을 작성합니다.
jar {
// Jar 파일 이름을 지정
archiveName 'lint-example.jar'
// Android Lint용 매니페스트 속성에
// 자체 작성한 Issue 저장소를 지정
manifest {
attributes("Lint-Registry":
"com.example.ExampleIssueRegistry")
}
}
Android Studio의 Terminal에서 다음 gradle 명령을 사용하여 jar를 만듭니다.
$ ./gradlew clean
$ ./gradlew assemble
빌드 된 jar는 아래에 출력됩니다. build/libs/
빌드한 독자 Custom Lint rule (jar)을 다음으로 복사하여 Android Studio에서 사용할 (참조할 수) 있도록 합니다.
# MAC, Linux
$ mkdir ~/.android/lint
$ cp 独自カスタムLint.jar ~/.android/lint
# Windows
> cd Users¥ユーザ名
> mkdir .android¥lint
> copy 独自カスタムLint.jar .android¥lint
Android Studio를 시작하면 독자 Custom Lint rule이 활성화되어 있습니다.
(편집기에서 문제 부분의 강조 표시)
(Inspect Code …에서 문제 부분 나열)
File > Other Settings > Default Settings …에서 Default Settings 대화 상자를 열고 왼쪽 창에서 Editor > Inspections을 선택 Editor > Inspections 설정을 엽니다.
모든 서드파티 Lint Custom rule은 Android > Lint > Collectness에 해당하므로 Error from Custom Lint Check
와 Warrning from Custom Lint Check
의 체크를 제외할 경우, 검사도 해제됩니다. (fig-1)
(fig-1)
주의 : lint 명령에서 사용할 수 없습니다
이번에 작성한 독자 Lint Custom rule은 Android SDK의 lint 명령줄 도구에서는 사용할 수 없습니다.
Android SDK/tools/lib/의 Lint 라이브러리 (jar)는 AST(추상 구문 트리)에 lombok.ast만을 사용하여 com.intellij 관련 API가 포함되어 있지 않기 때문입니다.
$ lint --list
Could not load custom rule jar file 独自カスタムLint.jar
java.lang.NoClassDefFoundError:
com/android/tools/lint/detector/api/Detector$JavaPsiScanner
샘플・프로젝트의 Lint Custom rule과 Android Studio의 검사를 이용하여 단일 책임의 원칙을 실천해보겠습니다.
샘플・프로젝트의 사용자 정의 Lint 규칙에서 Android Studio 편집기 화면은
복합 책임의 완전한 지적이 아니므로, 익숙해지기까지의 보조 정도로 생각하십시오.
샘플・프로젝트의 사용자 정의 Lint 규칙은 자동으로 소스 코드를 생성하는 것은 아닙니다. 우선은 나름대로의 코드를 작성해보세요.
제한 사항
이 점은 수정 목적이 하나의 경우에 한정됩니다.
“메소드가 변경하는 필드 변수 (상태)”에 대해 4가지 지적을 합니다.
복합 메소드의 지적은 완벽하지 않습니다. 오판도 있으므로 제안 내용에 연연하지 마십시오.
결국은 책임 독립의 메소드를 목표로 합니다.
우선은 책임 독립과 책임 공유의 메소드를 목표로 합니다.
단일 책임의 원칙을 제대로 판단하려면 기계적으로 실현 될 수 없는 역할의 추상화가 필요합니다. 지적이 없는 것이 이상적이지만, 상태 변경 목적이 비단일시의 현실 목표는 “책임 혼합을 지적되지 않는다
“이지요.
가장 중요한 것은,
…을 의식하여 클래스를 작게하는 것이라고 생각합니다.
단일 책임의 원칙의 소감은
…를 충족하는 것으로 생각합니다.
요구 사양 자체가 흐름 절차적이어도, “무엇이 무엇에 메시지를 보내느냐“라는 객체지향 프로그래밍의 관점을 잊지 않도록
유의하고 싶습니다.
comments powered by Disqus
Subscribe to this blog via RSS.
LazyColumn/Row에서 동일한 Key를 사용하면 크래시가 발생하는 이유
Posted on 30 Nov 2024