InfoGrab DocsInfoGrab Docs

추상화 재사용 가이드라인

GitLab 코드베이스에서 Service 클래스, Finder, Presenter, Serializer, Model 등 다양한 추상화 계층을 올바르게 재사용하는 방법과 각 계층의 역할 및 제약 사항을 설명합니다.

GitLab이 성장함에 따라 코드베이스 전반에 걸쳐 다양한 패턴이 등장했습니다. Service 클래스, Serializer, Presenter 등이 그 예입니다. 이러한 패턴 덕분에 코드를 쉽게 재사용할 수 있게 되었지만, 동시에 특정 상황에서 잘못된 추상화를 실수로 재사용하기도 쉬워졌습니다. 이 가이드라인이 필요한 이유 # 코드 재사용은 좋은 관행이지만, 때로는 잘못된 추상화를 특정 사용 사례에 억지로 끼워 맞추는 결과를 초래할 수 있습니다. 이는 유지보수성, 문제 디버깅 용이성, 심지어 성능에도 부정적인 영향을 미칠 수 있습니다. 예를 들어, IssuesFinder 에서 ProjectsFinder 를 사용하여 특정 프로젝트에 속한 이슈만 조회하도록 제한하는 경우를 들 수 있습니다. 처음에는 좋은 아이디어처럼 보일 수 있지만, 두 클래스 모두 세밀한 제어가 거의 불가능한 매우 높은 수준의 인터페이스를 제공합니다. 이는 쿼리의 상당 부분이 ProjectsFinder 의 내부 동작에 의해 제어되기 때문에 IssuesFinder 가 더 최적화된 데이터베이스 쿼리를 생성하지 못할 수 있음을 의미합니다. 이 문제를 해결하려면 ProjectsFinder 를 직접 사용하는 대신, ProjectsFinder 가 사용하는 동일한 코드를 사용해야 합니다. 이를 통해 동작을 더 잘 구성할 수 있으며, 코드의 동작에 대한 더 많은 제어권을 갖게 됩니다. 이를 설명하기 위해 IssuableFinder#projects 의 다음 코드를 살펴보겠습니다: return @projects = project if project? projects = if current_user && params[:authorized_only].presence && !current_user_related? current_user.authorized_projects elsif group finder_options = { include_subgroups: params[:include_subgroups], exclude_shared: true } GroupProjectsFinder.new(group: group, current_user: current_user, options: finder_options).execute else ProjectsFinder.new(current_user: current_user).execute end @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) 여기서 우리는 세 가지 다른 방식을 사용하여 데이터의 범위를 지정할 프로젝트를 결정합니다. 그룹이 지정된 경우 GroupProjectsFinder 를 사용하여 해당 그룹의 모든 프로젝트를 가져옵니다. 표면적으로는 무해해 보입니다. 사용하기 쉽고 두 줄의 코드만 필요합니다. 실제로는 상황이 매우 복잡해질 수 있습니다. 예를 들어, GroupProjectsFinder 가 생성하는 쿼