공통 라이브러리는 좋은 생각입니까?


16

저는 항상 "공통 라이브러리"가 좋은 생각이라고 생각했습니다. 즉, 몇 가지 다른 응용 프로그램에 필요한 공통 기능이 포함 된 라이브러리를 의미합니다. 코드 중복 / 이중화가 줄어 듭니다.

나는 최근에 이것이 실제로 나쁜 생각이고 "반 패턴 (anti-pattern)"이라고 말하기까지 한 기사 (지금 찾을 수 없음)를 읽었다.

이 접근법에는 단점이 있지만. 변경 버전 관리 및 관리는이 라이브러리를 사용하는 앱 제품군에 대한 회귀 테스트를 의미합니다.

나는 새로운 (Golang) 프로젝트에 대해 틀에 박힌 상태에 처해 있습니다. 코드 중복 제거 기술은 수년에 걸쳐 나에게 몰려 들었지만 이번에는 시도해보아야 할 것 같습니다.

이 글을 쓰는 동안,이 "일반적인 lib"접근 방식이 아키텍처에 대한 축소의 결과라고 생각하기 시작했습니다. 아마도 내 디자인에 더 많은 생각이 필요할까요?

생각을 듣고 싶습니다.


2
My 2 cents ... 만약 시스템 중 하나가 그 변경을 필요로한다면 공통 API를 변경해야한다면, 그 API 또는 라이브러리는 전혀 일반적인 라이브러리가 아닙니다
Raja Anbazhagan

1
코드 복제와 커플 링 사이에는 근본적인 균형이 있습니다. 귀하의 질문은 그 대표적인 예입니다. 둘 사이의 균형은 아마도 코드가 궁극적으로 실행될 환경에 달려있을 것입니다.
Joel Cornett

내가 아는 대부분의 C 개발자는 "도구 상자"라고하는 유틸리티 모음을 가지고 있습니다. 그러나 일반적으로 하나의 포함 할 수없는 라이브러리로 수집되지 않습니다. 더 "선택 및 선택"입니다.
Mark Benningfield

2
누군가 아파치를 부르고이 광기를 고치세요. Apache Commons
Laiv

답변:


21

라이브러리와 재사용은 절대적으로 좋은 것입니다. 그들은 하나의 거대한 단점이 있습니다. 즉, 신중하게 관리하지 않으면 다른 곳으로 가지 않는 모든 확률과 끝을 보유하는 부엌의 서랍과 같습니다.

64 비트 시스템에 대한 전체 비즈니스 단위의 코드 (대부분 나에게 새로운 것)의 첫 번째 포트를 담당하고 빌드 및 패키징에 대한 완전한 점검을 수행했을 때이 작업이 진행되는 것을 보았습니다. 우리는 클라이언트가 "A, B, D 및 F를 수행하는 시스템과 M을 수행하는 시스템을 원합니다. 그리고 N은 당신이 아직 통합하지 않은 약간 다른 접착제입니다. " 이 모든 것이 공통적으로 가지고 있던 것은 수십 년 동안 사람들이 재사용 할 수 있어야한다고 생각한 모든 것을 축적 한 쓰레기 서랍 라이브러리였습니다. 간단히 말해서 라이브러리의 코드 중 일부는 '. 우리는 공통 라이브러리가 실제로 필요하기 때문에가 아니라 공통 라이브러리가 설치되도록 의존성을 구축하고 유지하는 데 많은 귀중한 시간을 소비했습니다.

도덕은 라이브러리가 클래스처럼 취급되어야하고 너무 많은 책임으로 과부하되지 않아야한다는 것입니다. 작성하는 모든 프로그램이 둘 다 사용하더라도 JSON 파서를 선형 대수 함수가있는 동일한 라이브러리에 두지 마십시오.

그것들을 불연속으로 유지하면 많은 이점이 있으며, 그중 가장 큰 장점은 개발자와 패키저가 정크 서랍과 함께 제공되는 수하물을 포함하는 대신 자신의 제품이 실제로 필요한 것에 대한 자세한 설명을 강요한다는 것입니다. 빌드 된 패키지를 사용하여 시스템을 설정할 때 세분화 된 종속성은 필요한 부품 만 설치되도록합니다. 보관소를 무시하고 오래되고 잔인한 물건을 계속해서 컴파일하더라도 더 이상 사용하지 않는 것은 배송 대상으로 누출되지 않습니다.

물론 libc많은 함수를 하나의 라이브러리에 넣는 것과 같은 예외가 있습니다. 그것은 X 를 제외한 다른 방법 이 항상 나쁜 연습 이라고 주장하는 홀을 열광적으로 맹목적으로 청각하는 대신 그 방법으로 얻는 이점을 추론 할 수있는 경우 중 하나입니다 .


*이 과정에서 6 년 만에 처음부터 다시 컴파일되지 않은 바이너리가 발견되었습니다.

** 수십 년 된 코드에는 아무런 문제가 없습니다. 우리는 현대의 이익을 위해서만 그것들을 재 작성하는 바보 였을 정도로 입증 된 많은 중요한 알고리즘을 가지고있었습니다.


1
제 경험에 따르면, 라이브러리 이름을 "공통"으로 지정하려는 경우 문제가 발생합니다.
Karl Bielefeldt

9

당황하게도 저는 수십 년 전 팀 환경에서 "공통"라이브러리를 소개했습니다. 나는 몇 개월 만에 느슨하게 조정 된 팀 환경에서 일어날 수있는 역학을 실제로 이해하지 못했습니다.

내가 그것을 소개했을 때 나는 그것을 명확하게 생각하고 또한 우리가 매일 우리가 유용하다고 생각하는 것들, 그것이 미니멀리스트 도서관이되도록 의도되어 있으며, 도서관은 도서관 이외의 다른 것에 의존해서는 안된다는 것을 문서화했다 새로운 프로젝트에서 가능한 한 쉽게 배포 할 수 있도록 표준 라이브러리. 당시 제 생각은 그것이 특정 영역에서 우리가 매일 유용하다고 생각한 것들에 대한 표준 라이브러리에 대한 우리의 작은 확장이었습니다.

그리고 그것은 충분히 시작되었습니다. 우리 common/math*는 선형 대수학에서 종종 무거운 컴퓨터 그래픽 작업을하고 있었기 때문에 우리 모두가 일상적으로 사용 하는 수학 라이브러리 ( )로 시작했습니다 . 그리고 우리는 종종 C 코드로 interoping 된 이후, 우리는 몇 가지 유용한 유틸리티 기능에 합의처럼 find_index하는 달리std::findC ++에서는 C 함수의 작동 방식을 모방 한 반복자 대신 시퀀스에서 찾은 요소에 색인을 반환합니다.이 종류의 것들은 약간 절충 적이지만 미니멀하고 널리 사용되어 모든 사람에게 친숙하고 실용적입니다. , "공통"또는 "표준"을 만들려고 할 때 즉각적인 친숙 함은 매우 중요한 기준입니다. 왜냐하면 그것이 "공통적"이라면, 그 결과에 대해 친숙한 품질을 가져야하기 때문입니다. 채택 및 일일 사용.

그러나 시간이 지남에 따라 사람들이 개인적으로 사용하는 것을 추가하기 시작하면서 다른 사람이 사용할 수 없다고 생각하면서 라이브러리를 사용하려는 사람을 찾기 위해 라이브러리의 디자인 의도가 손가락에서 벗어났습니다. 그리고 나중에 누군가는 일반적인 GL 관련 루틴을 위해 OpenGL에 의존하는 기능을 추가하기 시작했습니다. 또한 우리는 Qt를 채택했고 사람들은 Qt에 의존하는 코드를 추가하기 시작했습니다. 그래서 이미 공통 라이브러리는 두 개의 외부 라이브러리에 의존했습니다. 어느 시점에서 누군가는 응용 프로그램 특정 셰이더 라이브러리에 의존하는 일반적인 셰이더 루틴을 추가했으며 그 시점에서 Qt, OGL 및 응용 프로그램 별 셰이더 라이브러리를 가져 와서 작성하지 않고 새 프로젝트에 배포 할 수도 없었습니다. 프로젝트를위한 사소한 빌드 스크립트 그래서이 절충되고 상호 의존적 인 혼란으로 바뀌 었습니다.

그러나이 라이브러리에 들어가야 할 것과 그렇지 말아야 할 것에 대해 토론함으로써 "공통"으로 간주되는 것이 "공통"이 무엇인지에 대한 엄격한 규칙을 설정하지 않으면 매우 주관적인 아이디어로 쉽게 변할 수 있다는 것을 발견했습니다. 모두가 매일 유용하다고 생각하는 것. 표준이 느슨해지면 모든 사람이 매일 유용하다고 생각하는 것에서 다른 개발자에게 도움이 가능성이 있는 단일 개발자가 유용하다고 생각하는 것까지 신속하게 저하되며 , 그 시점에서 라이브러리는 매우 빠른 절충안으로 분해됩니다. .

그러나 그 시점에 도달하면 일부 개발자는 프로그래밍 언어가 마음에 들지 않는 간단한 이유로 추가를 시작할 수 있습니다. 그들은 for 루프 또는 함수 호출의 구문을 좋아하지 않을 수 있습니다.이 시점에서 라이브러리는 언어의 기본 구문과 싸우는 것들로 가득 차기 시작하여 실제로는 그렇지 않은 몇 줄의 간단한 코드 줄을 대체합니다. 이러한 속기를 소개 한 개발자에게만 익숙한 하나의 이국적인 코드로 로직을 복제합니다. 그런 개발자는 그러한 속기를 사용하여 구현 된 공통 라이브러리에 더 많은 기능을 추가하기 시작할 수 있습니다. 이 시점에서 공통 라이브러리의 중요한 부분은이 이국적인 속기들과 짜여져 있습니다.이 속기들을 소개 한 개발자에게는 아름답고 직관적으로 보일 수 있지만, 추악하고 외국적이고 다른 사람들에게는 이해하기 어렵습니다. 그리고 그 시점에서 나는 "공통"과 "낯선"이 정반대의 아이디어이기 때문에 진정으로 "공통"을 만드는 것에 대한 희망이 사라진다는 것을 알고 있다고 생각합니다.

최소한 느슨하게 조율 된 팀 환경에는 모든 종류의 웜 캔이 있습니다. 라이브러리는 "일반적으로 사용하는 것"만큼 광범위하고 일반화 된 야망을 가진 라이브러리가 있습니다. 그리고 근본적인 문제는 다른 무엇보다도 느슨한 조정 이었을지 모르지만, 수학 루틴을 제공하기위한 라이브러리와 다른 어떤 것보다 더 특이한 목적을 제공하기위한 적어도 여러 라이브러리는 아마도 그것의 관점에서 크게 저하되지 않을 것입니다 순도 및 종속성을 "공통"라이브러리로 디자인합니다. 그래서 돌이켜 보면 훨씬 더 명확한 디자인 의도를 가진 라이브러리 측면에서 잘못하는 것이 훨씬 낫다고 생각합니다. 또한 수년에 걸쳐 목적이 좁고 적용 가능성이 좁다는 것은 근본적으로 다른 아이디어라는 것을 알았습니다.

또한 나는 적어도 약간 비현실적이며, 미학에 대해 너무 많은 관심을 기울이고 있지만, 도서관의 질 (그리고 아마도 "아름다움")에 대한 내 생각을 인식하는 경향은 그것의 가장 강한, 비슷한 방식으로 당신이 나에게 세상에서 가장 맛있는 음식을 선물했지만 같은 접시에 썩은 냄새가 나는 것을 바르면 전체 접시를 거부하는 경향이 있습니다. 그리고 당신이 저와 같은 점에서 모든 종류의 추가를 "공통"이라고 부르는 것을 만들면, 측면에 썩은 것이있는 그 유사 판을 볼 수 있습니다. 마찬가지로 도서관이 구성되고 이름이 지정되고 문서화되는 것이 좋을 것 같습니다. 시간이 지남에 따라 점점 더 많은 추가를 초대하지 마십시오. 그리고 여기저기서 썩은 것들을 만들었 기 때문에 개인 창작물에도 적용 할 수 있으며, 그것이 가장 큰 접시에 추가되지 않으면 훨씬 덜 오염됩니다. 사물을 작고 매우 특이한 라이브러리로 분리하면 코드를 더 잘 분리하는 경향이 있습니다. 단순히 모든 것을 결합하는 것이 훨씬 편리하지 않다는 장점 때문입니다.

코드 중복 제거 기술은 수년에 걸쳐 나에게 몰려 들었지만 이번에는 시도해보아야 할 것 같습니다.

귀하의 경우에 제안 할 수있는 것은 코드 중복 제거를 쉽게 시작하는 것입니다. 나는 잘 테스트되지 않았고 오류가 발생하기 쉬운 코드의 큰 조각을 복사하여 붙여 넣거나 붙여 넣을 것이라고 말하지 않으며, 미래에 변경이 필요할 확률이 높은 사소한 코드를 복제합니다.

그러나 특히 "공통"라이브러리를 만들려는 마음가짐이 있다면, 여러분이 원하는 것은 광범위하게 적용 가능하고 재사용 성이 높으며 아마도 10 년 전과 마찬가지로 오늘날에도 유용한 것으로 생각되는 것을 만들고자합니다. , 때로는이 어려운 품질을 달성하기 위해 복제가 필요하거나 원하는 경우도 있습니다. 복제가 실제로 디커플링 메커니즘으로 사용될 수 있기 때문입니다. 비디오 플레이어를 MP3 플레이어와 분리하려면 배터리와 하드 드라이브와 같은 것을 복제해야합니다. 그들은 이러한 것들을 공유 할 수 없거나 서로 분리되어 서로 독립적으로 사용될 수 없으며, 그 시점에서 사람들이 MP3 재생 만하면 더 이상 장치에 관심이 없을 수 있습니다. 그러나이 두 장치를 분리 한 후 얼마 지나지 않아 MP3 플레이어는 비디오 플레이어와는 다른 배터리 디자인이나 작은 하드 드라이브의 이점을 누릴 수 있습니다.이 시점에서 더 이상 아무것도 복제하지 않습니다. 이 상호 의존적 장치를 두 개의 독립된 독립 장치로 분리 할 수 ​​있도록하기 위해 처음에 복제로 시작한 것은 나중에 더 이상 중복되지 않는 설계 및 구현을 산출 할 수 있습니다.

라이브러리를 사용하는 관점에서 사물을 고려해 볼 가치가 있습니다. 실제로 사용 하시겠습니까?코드 중복을 최소화하는 라이브러리? 자연스럽게 다른 라이브러리에 의존하기 때문에 그렇지 않을 가능성이 있습니다. 그리고 다른 라이브러리는 코드 복제를 피하기 위해 다른 라이브러리에 의존 할 수 있습니다. 오디오 파일로드 및 재생과 같은 기본 기능을 얻기 위해 50 개의 서로 다른 라이브러리를 가져 오거나 링크해야 할 때까지 매우 까다로워집니다. . 한편, 그러한 오디오 라이브러리가 의도적으로 독립성을 달성하기 위해 여기저기서 일부를 복제하기로 선택한 경우, 새로운 프로젝트에서 사용하기가 훨씬 쉬워지고, 그 이후로 거의 자주 업데이트 할 필요가 없을 가능성이 있습니다. ' 종속 외부 라이브러리가 변경되어 오디오 라이브러리에 필요한 것보다 훨씬 일반적인 목적을 달성하려고 시도 할 수 있으므로 변경해야합니다.

따라서 때로는 라이브러리를 분리하고 독립적으로 만들기 위해 라이브러리를 분리하고 독립적으로 만들기 위해 의도적으로 약간 복제 (의식적으로, 게으름에서 벗어나지 않음-실제로는 부지런함에서 벗어나지 않음)를 선택하는 것이 좋습니다. 심지어 안정성 (심각한 커플 링이 더 이상 없음). 하나의 프로젝트에서 다음과 몇 년 동안 지속될 수있는 가장 재사용 가능한 라이브러리를 디자인하려면 범위를 최소로 좁히는 것 외에도 실제로 여기에 약간의 복제를 고려하는 것이 좋습니다. 또한 자연스럽게 단위 테스트를 작성하고 수행중인 작업에서 철저하게 테스트되고 신뢰할 수 있는지 확인하십시오. 이것은 단지 하나의 프로젝트를 넘어서는 지점으로 일반화하기를 정말로 원하는 라이브러리에만 해당됩니다.


3

라이브러리에 넣는 것을 고려할 수있는 세 가지 범주의 함수가 있습니다.

  1. 모두에게 재사용할만한 가치가있는 것들.
  2. 조직에서 재사용 할 가치가있는 것.
  3. 재사용 할 가치가없는 물건.

카테고리 1은 표준 라이브러리 존재 해야하는 것입니다 . 그러나 어떤 이유로 아무도 만들지 않았습니다. 이 경우 라이브러리를 오픈 소스로 만드십시오. 작업을 공유하면 다른 사람에게 도움이 될뿐만 아니라 다른 사용자로부터 버그 보고서와 패치를받을 수 있으므로 도움이됩니다. 누군가 라이브러리에 기여할 것이라고 의심되면 실제로 카테고리 2 또는 3 인 기능을 처리하는 것일 수 있습니다.

두 번째 범주는 당신이 계속해서 필요로하는 것들이지만, 세계 어느 누구도 그것을 필요로하지 않습니다. 예를 들어, 사내 개발 백엔드 시스템과 통신하기 위해 모호한 네트워크 프로토콜을 구현합니다. 이 경우 새로운 응용 프로그램의 개발 속도를 향상시키기 위해 사내 라이브러리에 해당 내용을 넣는 것이 좋습니다. 피처 크립의 영향을 너무 많이받지 않고 실제로 카테고리 1 또는 3에 맞는 것을 포함하기 시작하십시오. 또한 모듈화에 대한 Blrfl의 조언은 매우 좋습니다. 모 놀리 식 Conor Corp. 라이브러리를 만들지 마십시오. 별도의 기능을 위해 여러 개의 개별 라이브러리를 만듭니다.

범주 3은 라이브러리로 라이브러리를 옮기는 것이 가치가 없거나 다른 응용 프로그램에서 정확히 해당 형식으로 다시 필요할지 확신 할 수없는 기능을 구현하는 기능입니다. 이 기능은 개발 된 응용 프로그램의 일부로 유지되어야합니다. 의심스러운 경우이 범주에 속할 수 있습니다.


1

거의 모든 언어에는 공통 / 표준 라이브러리가 있으므로 널리 사용되는 것이 좋습니다. 휠을 재발 명하기보다는 다양한 작업에 세 번째 부분 라이브러리를 사용하는 것이 일반적으로 좋은 생각으로 여겨지지만, 비용 / 혜택과 라이브러리의 품질은 각 경우마다 분명히 평가되어야합니다.

그런 다음 관련이없는 프로젝트에서 개별 개발자 또는 기관이 사용하는 "공통 유틸리티"라이브러리가 있습니다. 이것은 안티 패턴으로 간주 될 수 있는 일종의 라이브러리 입니다. 내가 본 경우, 이러한 라이브러리는 표준 라이브러리 또는 잘 알려진 타사 라이브러리의 기능을 비표준적이고 잘못 문서화 된 방식으로 복제합니다.


these libraries just replicate functionality from standard libraries이것은 완전히 나쁜 일이 아닙니다. 자바 스크립트에서 기존 js 엔진에 대한 지원을 추가하기 위해 기존의 것을 이미 구현 한 라이브러리를 추가했습니다. 또한 이전 SDK에 대한 Android 지원 라이브러리도 있습니다.
svarog

@ svarog : 기본적으로 지원하지 않는 구형 엔진의 새로운 표준에서 기능을 에뮬레이트하는 "polyfills"를 생각하고 있습니까? 이러한 목적으로 사용 가능한 잘 알려진 오픈 소스 라이브러리가 있기 때문에 직접 작성해야 할 이유가 없습니다.
JacquesB

0

팀간에 공유되는 대부분의 라이브러리는 해결하는 것보다 더 많은 문제를 일으 킵니다. "지옥으로가는 길은 좋은 의도로 포장되어 있습니다."

아래의 대부분 을 충족하는 라이브러리는 예외입니다 .

  • 장기적인 유지 보수 자금 확보
  • 전담 지원 팀 / 커뮤니티 보유
  • 버그 추적기
  • 광범위한 테스트 적용
  • 잘 정의 된 단일 목적
  • 표준 또는 준 표준 라이브러리 이외의 종속성 (빌드 및 런타임 모두)이 없습니다.
  • 공개 API와 내부 정보를 명확하게 구분
  • 모든 / 많은 사용자가 새로운 기능과 릴리스에 동의 할 수 있도록 커뮤니케이션 채널과 프로세스를 갖추십시오.

스타트 업이 아닌 일반적인 회사 내부에서는 팀간에 공유되는 라이브러리에 대해 위의 조건이 거의 존재하지 않습니다. 대부분의 회사 팀은 라이브러리가 아닌 제품을 제공하기 위해 비용을 지불하기 때문입니다. 일부 회사는 Google의 모노 레포와 같은 성공적인 공유 전략을 가지고 있지만 구축 및 테스트 인프라에 대한 투자가 매우 높습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.