- CrawlerWithReturn 으로 된 것은 함수의 기본에 맞게끔 모두 return 문을 사용해서 받아 온 후에 main() 에서 실행합니다.
- 함수의 정석이라고 할 수 있겠죠. 근데 매번 파라미터를 넘기고 변수로 return 값을 받기가 귀찮네요.
- 그래서 좀 더 편하게 해보려고 인스턴스 변수를 사용해 봤습니다.
- 그런데 왠지 정석이 아닌것 같아서 좀 쓰기가 그렇습니다만 파라미터로 넘기는 것도 없고 리턴으로 받는 것도 없게 되서
- 프로그램 짜기가 좀 더 편해졌습니다. 다만, 인스턴스 변수를 쓰기 떄문에 함수의 흐름을 제대로 보고 실행시켜 줘야겠지요..
- 각각 언제 활용해야 하며 장,단점이 무엇일까요?
- 이 생각을 오랫동안 했었는데 물어보기 좀 그래서 놔뒀었는데.. 정말 궁금해졌습니다.
- 혹시 이것보다 더 좋은 방법이 있을까요?
- Code Complete 이 책의 p.352 페이지를 보면 클래스의 멤버 데이터를 생성자에서 초기화 한다 이렇게 써있네요.
- 루틴의 변수를 각 루틴 내에서 초기화해야 하는것처럼, 클래스의 데이터도 생성자에서 초기화 되어야 한다. 만약 메모리가 생성자에서 할당된다면, 소멸자에서 해제되어야 한다.
- 라고 써져있는걸 보니.. 제가 변칙적으로 쓰는건 좀 아닌것 같네요?
data = ReadData()
results = CalculateResultsFromData(data)
PrintResults(results)
- 이 예제의 내적인 개념은 의존성에 관한 것
- 3번째 명령문은 2번째 명령문에 의존하며, 2번째 명령문은 1번째 명령문에 의존한다. 이 예제에서 한 명령문이 다른 명령문에 의존한다는 사실은 루틴의 이름으로부터 명확하게 알 수 있다. 다음 코드에서는 의존성이 덜 분명하다.
revenue.ComputeMonthly();
revenue.ComputeQuarterly();
revenue.ComputeAnnual();
- 이 예제에서 분기별 수입 계산은 월별 수입이 이미 계산되어 있다고 가정하고 있다. 회계에 대해서 알고 있다면, 또는 상식적으로 분기별 수입은 1년 수입이 계산되기 전에 계산되어져야 한다는 것을 알 수 있을 것이다. 이러한 계산들 간에는 의존성이 있다. 하지만 이 코드를 읽는 것만으로는 그러한 관계가 분명하지 않다. 이 코드에서는 그러한 의존성이 분명하지 않으며 실제로 감추어져 있다.
ComputeMarketinExpense
ComputeSalesExpense
ComputeTravelExpense
ComputePersonnelExpense
DisplayExpenseSummary
- ComputeMarketingExpense()가 다른 모든 루틴에서 자신의 데이터를 넣을 클래스 멤버 변수들을 초기화한다고 가정해 보자. 그런 경우라면, 다른 루틴들보다 먼저 호출되어야 한다. 하지만 이 코드를 보고 그러한 내용을 어떻게 알 수 있을까? 이 루틴 호출은 아무런 매개변수를 갖고 있기 않기 때문에, 이 루틴들은 클래스 데이터에 접근하고 있다고 추측할 수 있을 것이다. 하지만 이 코드를 봐서는 확실하게 알 수 없다.
명령문들이 특정한 순서대로 작성되어야 하는 의존성을 갖고 있을 때, 의존성을 분명히 하기 위한 단계를 밟아야 한다.
- 의존성이 분명하도록 코드를 구성한다.
- 의존성이 분명하도록 루틴의 이름을 작성한다.
- 의존성을 분명히 하기 위해서 루틴 매개변수를 사용하라
InitializeExpenseData(expenseData)
ComputeMarketingExpense(expenseData)
ComputeSalesExpense(expenseData)
ComputeTravelExpense(expenseData)
ComputePersonnelExpense(expenseData)
DisplayExpenseSummary(expenseData)
- 모든 루틴들이 expenseData를 사용하기 때문에, 이 루틴들이 동일한 데이터를 다루고 있으며 명령문의 순서가 중요할지도 모른다는 힌트를 얻을 수 있다.
- 이 예제에서는 루틴을 expenseData를 입력으로 받고 갱신된 expenseData를 출력으로 반환하는 함수로 변환하여, 코드에 순서 의존성이 있음을 보다 명확하게 만들 수 있다.
expenseData = InitializeExpenseData(expenseData)
expenseData = ComputeMarketingExpense(expenseData)
expenseData = ComputeSalesExpense(expenseData)
expenseData = ComputeTravelExpense(expenseData)
expenseData = ComputePersonnelExpense(expenseData)
DisplayExpenseSummary(expenseData)
- 또한 이 경우에서처럼 데이터의 실행 순서가 중요하지 않다는 것을 암시할 수도 있다.
ComputemarketingExpense(marketingData)
ComputeSalesExpense(salesData)
ComputeTravelExpense(travelData)
ComputePersonnelExpense(personnelData)
DisplayExpenseSummary(marketingData, salesData, travelData, personnelData)
- 처음 네 줄에 있는 루틴들이 공통적으로 사용하는 데이터가 없기 떄문에, 이 코드는 이 루틴들이 호출되는 순서가 중요하지 않음을 암시하고 있다. 다섯 번째 줄에 있는 루틴은 처음 4개의 루틴으로부터 얻은 데이터를 사용하기 때문에, 이 함수는 아프이 4개의 루틴 다음에 실행되어야 한다는 것을 추측할 수 있다.
의존성의 분명하지 않은 부분은 주석으로 문서화한다.
` 지출 데이터를 계산한다. 각 루틴들은 멤버 데이터 expenseData에 접근한다.
` DisplayExpenseSummary는 다른 루틴들에서 계산된 데이터에 의존하기 떄문에
` 마지막에 호출되어야 한다.
-
이 코드는 순서 의존성을 만들기 위한 기법을 사용하지 않고 있다. 물론, 주석보다는 그러한 기법들을 사용하는 것이 더 좋은 방법이겠지만, 만약 제약이 많은 코드를 유지 보수하고 있거나 어떠한 이유 때문에 코드 자체를 개선할 수 없다면, 코드의 약점을 보완하기 위해서 주석을 사용한다.
-
어설션이나 오류 처리 코드로 의존성을 검사한다.
페이스북 윤태호님 답변