[Flutter] forEach vs for-in

Tykan·2021년 9월 7일
1
post-thumbnail

🙀 forEach를 쓰지 말라고?

좀 더 나은 코드 작성 습관 형성과 팀 내부에서 코드 규칙을 맞추기 위해 lint 옵션들을 사용한다. flutter 프로젝트에서는 flutter_lints 라는 플러터팀의 패키지를 기반으로 일부 커스텀하여 사용하고 있다.

그 중에 forEach에 대해 의문점이 생긴 linting rule이 있었다.

avoid_function_literals_in_foreach_calls
말 그대로 forEach 함수에서 함수 리터럴을 사용하지 말라는 것이다.

일단 공식 문서부터 살펴보자.

forEach() functions are widely used in JavaScript because the built in for-in loop doesn’t do what you usually want. In Dart, if you want to iterate over a sequence, the idiomatic way to do that is using a loop.

// 좋은 예
for (var person in people) {
  ...
}
// 나쁜 예
people.forEach((person) {
  ...
});

플러터에 있는 forEach 코드를 보면 아래와 같다.

void forEach(void f(E element)) {
  for (E element in this) f(element);
}

forEach는 결국 for-in으로 작동한다. 뭐가 문제지...?
왜 avoid_function_literals_in_foreach_calls 룰이 있을까?

function_literals이라는 것이 주요한 차이다.
공식 문서의 예시를 보면 함수 리터럴로 생성된 함수를 루프시키고 있다.

people.forEach(print);

위와 같이 함수 리터럴이 아닌 경우 사용해도 무방하다고 설명하고 있다.

설명을 보더라도, 크게 성능 이슈의 문제는 없다.
하지만 내 생각에는 이건 결국 flow control의 문제다.

기본적인 for문을 쓰는 경우 break, continue, return을 통해 Iterable에 대한 반복 루프 제어가 가능하다.
하지만 forEach는 이러한 제어가 불가하다.

즉 함수 리터럴을 사용한다는 것은 일반적으로 내가 반복문에서 엘리먼트에 대해서 추가적인 작업, 제어를 한다는 것인데, 이는 for문을 쓰는게 관용적이라는 말이다.

결론은?

기능 구현에 문제가 없다면, 편한대로 쓰자.

대부분의 상황에서 for문을 보다 짧게 쓰기 위해 forEach를 쓴다.
그렇다면 아래와 같이 더 forEach답게(?) forEach 문을 써보는게 어떨까.

(X) people.forEach((person)=> print(person));

(O) people.forEach(print);

(X) people.forEach((person){
  if(person.name == '철수'){
    print(person);
  }
});

(O) people.where((person)=>person.name=='철수').forEach(print);
profile
개발자 Theo :: 고민은 성장의 힘

0개의 댓글