순환 종속성을 해결하는 방법은 무엇입니까?
On 1월 1, 2021 by admin서로 종속 된 세 개의 클래스가 있습니다.
TestExecuter는 TestScenario의 요청을 실행하고 ReportGenerator 클래스를 사용하여 보고서 파일을 저장합니다. . 따라서 :
- TestExecuter는 ReportGenerator에 의존하여 보고서를 생성합니다.
- ReportGenerator는 TestScenario와 TestExecuter에서 설정 한 매개 변수에 의존합니다.
- TestScenario는 TestExecuter에 의존합니다.
이러한 종속성을 제거하는 방법을 찾을 수 없습니다.
public class TestExecuter { ReportGenerator reportGenerator; public void getReportGenerator() { reportGenerator = ReportGenerator.getInstance(); reportGenerator.setParams(this.params); /* this.params several parameters from TestExecuter class example this.owner */ } public void setTestScenario (TestScenario ts) { reportGenerator.setTestScenario(ts); } public void saveReport() { reportGenerator.saveReport(); } public void executeRequest() { /* do things */ } }
public class ReportGenerator{ public static ReportGenerator getInstance(){} public void setParams(String params){} public void setTestScenario (TestScenario ts){} public void saveReport(){} }
public class TestScenario { TestExecuter testExecuter; public TestScenario(TestExecuter te) { this.testExecuter=te; } public void execute() { testExecuter.executeRequest(); } }
public class Main { public static void main(String [] args) { TestExecuter te = new TestExecuter(); TestScenario ts = new TestScenario(te); ts.execute(); te.getReportGenerator(); te.setTestScenario(ts); te.saveReport() } }
수정 : 내 TestScenario 클래스에 대한 답변, 자세한 정보 :
public class TestScenario { private LinkedList<Test> testList; TestExecuter testExecuter; public TestScenario(TestExecuter te) { this.testExecuter=te; } public void execute() { for (Test test: testList) { testExecuter.executeRequest(test); } } } public class Test { private String testName; private String testResult; } public class ReportData { /*shall have all information of the TestScenario including the list of Test */ }
두 개의 테스트가 포함 된 시나리오의 경우 생성 될 xml 파일 :
<testScenario name="scenario1"> <test name="test1"> <result>false</result> </test> <test name="test1"> <result>true</result> </test> </testScenario >
댓글
답변
기술적으로 다른 답변에서 볼 수 있듯이 인터페이스를 사용하여 순환 종속성을 해결할 수 있습니다. 그러나 나는 당신의 디자인을 재고하는 것이 좋습니다. 추가 인터페이스의 필요성을 완전히 회피 하는 동시에 디자인이 더욱 단순해질 가능성은 거의 없다고 생각합니다.
ReportGenerator
가 TestScenario
에 직접 의존 할 필요는 없다고 생각합니다. TestScenario
에는 두 가지 책임이있는 것 같습니다. 테스트 실행에 사용되며 결과에 대한 컨테이너로도 작동합니다. 이것은 SRP 위반입니다. 흥미롭게도 해당 위반을 해결하면 순환 종속성도 제거됩니다.
따라서 보고서 생성기가 테스트 시나리오에서 데이터를 가져 오도록하는 대신 일부 값 개체를 사용하여 데이터를 명시 적으로 전달합니다. 즉,
reportGenerator.setTestScenario(ts);
다음과 같은 코드로
reportGenerator.insertDataToDisplay(ts.getReportData());
getReportData
에는 보고서에 표시 할 데이터의 컨테이너 역할을하는 값 개체 인 ReportData
와 같은 반환 유형이 있어야합니다. insertDataToDisplay
는 정확히 해당 유형의 객체를 기대하는 메소드입니다.
이 방법은 ReportGenerator
및
는 둘 다 다른 것에 의존하지 않는 ReportData
에 의존하며 처음 두 클래스는 더 이상 서로 의존하지 않습니다.
두 번째 접근 방식 : SRP 위반을 해결하려면 TestScenario
가 테스트 실행 결과를 보관하고 테스트 실행자를 호출하지 않도록합니다. 테스트 시나리오가 테스트 실행기에 액세스하지 않고 테스트 실행자가 외부에서 시작되고 결과를 다시 TestScenario
개체에 기록하도록 코드를 재구성하는 것이 좋습니다. 보여 주신 예에서 TestScenario
내부의 LinkedList<Test>
에 대한 액세스를 공개하고 execute
메서드에서 TestScenario
다른 곳으로, 아마도 TestExecuter
로 직접, 새 클래스로 TestScenarioExecuter
.
그러면 TestExecuter
는 TestScenario
에 의존합니다. 및 ReportGenerator
, ReportGenerator
도 TestScenario
에 종속되지만 TestScenario
는 다른 것에 의존하지 않습니다.
마지막으로 세 번째 접근 방식 인 TestExecuter
에도 너무 많은 책임이 있습니다. 테스트를 실행하고 ReportGenerator
에 TestScenario
를 제공하는 역할을합니다. 이 두 가지 책임을 두 개의 별도 클래스에 넣으면 순환 종속성이 다시 사라집니다.
문제에 접근하는 데 더 많은 변형이있을 수 있지만 일반적인 아이디어를 얻으시기 바랍니다. 핵심 문제는 책임이 너무 많습니다 . 이 문제를 해결하면 순환 종속성이 자동으로 제거됩니다.
댓글
- 답변 해 주셔서 감사합니다. 실제로 TestScenario의 모든 정보가 필요합니다. 마지막에 내 보고서를 생성 할 수 있으려면 : (
- @ sabrina2020 : 그리고 모든 정보를
ReportData
에 넣는 데 방해가되는 이유는 무엇입니까?질문을 편집하고saveReport
내부에서 일어나는 일을 좀 더 자세히 설명 할 수 있습니다. - 사실 내 TestScenario에는 테스트 목록이 포함되어 있으며 모두 이 경우 ReportData에 모든 정보가 포함되도록 보고서 xml 파일의 정보를 제공합니다. 자세한 내용은 제 답변을 수정하겠습니다. 감사합니다.
- +1 :
interfaces
. - @ sabrina2020 : 내 답변에 두 가지 접근 방식을 추가했습니다. 가장 적합한 것을 선택하세요.
답변
인터페이스를 사용하여 순환 종속성을 해결할 수 있습니다.
현재 디자인 :
제안 된 디자인 :
제안 된 설계 콘크리트 클래스는 다른 구체적인 클래스에 의존하지 않고 추상화 (인터페이스)에만 의존합니다.
중요 :
퍼포밍을 방지하려면 원하는 크리에이티브 패턴 (팩토리 일 수 있음)을 사용해야합니다. new
다른 구체적인 클래스 내부의 구체적인 클래스 또는 getInstance()
를 호출합니다. 공장 만이 구체적인 클래스에 의존합니다. 전용 공장이 과도하다고 생각하는 경우 Main
클래스가 공장 역할을 할 수 있습니다. 예를 들어 getInstance()
또는 iv id를 호출하는 대신 ReportGenerator
를 TestExecuter
에 삽입 할 수 있습니다. = “f465b4b90a”>
.
답변
TestExecutor
이후 내부적으로 만 ReportGenerator
를 사용하므로 이에 대한 인터페이스를 정의하고 TestScenario
의 인터페이스를 참조 할 수 있어야합니다. 그런 다음 TestExecutor
는 ReportGenerator
에 의존하고, ReportGenerator
는 TestScenario
및 TestScenario
는 아무것도 의존하지 않는 ITestExecutor
에 의존합니다.
이상적으로는 “모든 클래스에 대한 인터페이스를 정의하고이를 통해 종속성을 표현할 수 있지만 이것은 문제를 해결할 수있는 가장 작은 변화입니다.
File(filename).write(Report); Report = XMLResult(ResultData).toString(); ResultData = TestSuite(SingleTestLogic).execute(TestDataIterator(TestDetailsList))