과학 코드 작성시 깨끗하게 프로그래밍


169

나는 실제로 큰 프로젝트를 쓰지 않습니다. 나는 거대한 데이터베이스를 유지하거나 수백만 줄의 코드를 처리하지 않습니다.

내 코드는 주로 "스크립트"유형의 물건입니다. 수학 함수를 테스트하거나 "과학적 프로그래밍"을 시뮬레이션하는 것입니다. 내가 지금까지 노력한 가장 긴 프로그램은 수백 줄의 코드이며, 내가 작업하는 대부분의 프로그램은 약 150입니다.

내 코드도 쓰레기입니다. 내가 전에 쓴 파일을 찾으려고했던 다른 날에 이것을 깨달았지만 아마도 덮어 썼고 버전 컨트롤을 사용하지 않는다는 사실을 깨달았습니다.

내 코드의 스타일은 복잡하고 다른 방법이나 코드 행을 복사하여 대체 할 수있는 오래된 주석으로 채워져 있습니다. 변수 이름은 항상 매우 훌륭하고 설명 적이지만, 예를 들어 누군가 테스트하고 싶은 새로운 것을 추가하거나 변경함에 따라 코드가 맨 위에 겹쳐지고 덮어 쓰여 지며이 문제는 이제 빨리 테스트해야한다고 생각하기 때문에 crappy 변수 이름을 사용하기 시작하는 프레임 워크가 있고 파일이 팟에 들어갑니다.

제가 지금 진행하고있는 프로젝트에서 저는이 모든 것이 저를 크게 물려주는 단계에 있습니다. 그러나 문제는 (버전 제어를 사용하고 새로운 반복마다 새 파일을 만들고 어딘가에 텍스트 파일로 기록하는 것 외에 상황을 극적으로 도움이 될 것입니다)을 개선하는 방법을 모르겠습니다. 내 실제 코딩 스타일.

더 작은 코드를 작성하려면 단위 테스트가 필요합니까? OOP는 어때요? 더 큰 프로젝트에서 작업하는 대신 "과학적 프로그래밍"을 수행 할 때 좋고 깨끗한 코드를 신속하게 작성하는 데 어떤 종류의 접근 방식이 좋습니까?

나는 종종 프로그래밍 자체가 그렇게 복잡하지 않기 때문에 이러한 질문을한다. 프로그래밍으로 테스트하거나 연구하는 것은 수학이나 과학에 관한 것입니다. 예를 들어, 두 변수와 함수가 아마 그것을 처리 할 수있을 때 클래스가 필요한가? (이것은 일반적으로 프로그램의 속도가 더 빠른쪽에있는 것이 바람직한 상황이라고 생각합니다. 시뮬레이션의 25,000,000 회 이상의 시간 단계를 실행할 때는 다소 필요합니다.)

아마도 이것은 너무 광범위하고, 그렇다면 사과를 드리지만 프로그래밍 서적을 살펴보면 더 큰 프로젝트에서 종종 다루어지는 것 같습니다. 내 코드에는 OOP 가 필요 하지 않으며 이미 너무 짧아서 "아, 그러나 그렇게하면 파일이 천 줄씩 줄어 듭니다!" 작고 빠른 프로젝트에서 "다시 시작"하고 깨끗하게 프로그래밍하는 방법을 알고 싶습니다.

좀 더 구체적인 세부 사항을 제공하게되어 기쁘지만 조언이 많을수록 더 유용합니다. 파이썬 3으로 프로그래밍 중입니다.


누군가가 사본을 제안했습니다. 표준 프로그래밍 표준을 완전히 무시하는 것에 대해 이야기하고 있지 않다는 것을 분명히하겠습니다. 분명히 이러한 표준이 존재하는 이유가 있습니다. 그러나 다른 한편으로, 일부 표준 작업이 완료되었을 때 작성이 훨씬 빨 랐을 때 코드가 OOP라고하는 코드를 작성하는 것이 실제로 의미가 있습니까? 프로그램?

예외가 있습니다. 또한 단순한 표준 이상의 과학적 프로그래밍 표준이있을 수 있습니다. 나는 그들에 대해서도 묻는다. 과학 코드를 작성할 때 정상적인 코딩 표준을 무시해야하는지가 아니라 깨끗한 과학 코드를 작성하는 것입니다.


최신 정보

방금 "일주일이 아닌"업데이트를 추가 할 것이라고 생각했습니다. 당신의 모든 조언은 매우 도움이되었습니다. 나는 그래픽 제어를 위해 git kraken과 함께 버전 제어-git을 사용하고 있습니다. 사용하기 매우 쉽고 내 파일을 크게 정리했습니다. 더 이상 오래된 파일이 붙어 있거나 이전 버전의 코드가 "경우에 따라"주석 처리되지 않았습니다.

또한 pylint를 설치하고 모든 코드에서 실행했습니다. 한 파일은 처음에 음의 점수를 받았습니다. 그게 어떻게 가능한지 잘 모르겠습니다. 내 주요 파일은 ~ 1.83 / 10의 점수에서 시작했으며 현재 ~ 9.1 / 10입니다. 모든 코드는 이제 표준을 준수합니다. 또한 사라진 변수 이름을 업데이트하고 리팩토링 할 섹션을 찾는 내 자신의 눈으로 그것을 뛰어 넘었습니다.

특히, 나는이 사이트에서 최근 주요 기능 중 하나를 리팩토링하는 것에 대해 최근 질문을했으며 이제는 훨씬 깨끗하고 훨씬 짧습니다. 길고 부풀어 오르면 채워진 함수 대신 이제 절반 미만 크기와 진행 상황을 파악하기가 훨씬 쉽습니다.

다음 단계는 일종의 "단위 테스트"를 구현하는 것입니다. 내 주 파일에서 실행할 수있는 파일을 의미합니다. 어설 션 문과 시도 / 제외로 모든 기능을 볼 수 있습니다. 아마도 최선의 방법은 아니며 중복 코드가 많이 생성됩니다. 그러나 나는 계속해서 읽고 더 잘하는 방법을 알아 내려고 노력할 것입니다.

또한 이미 작성한 설명서를 크게 업데이트하고 Excel 스프레드 시트, 설명서 및 관련 용지와 같은 보충 파일을 github 저장소에 추가했습니다. 이제는 실제 프로그래밍 프로젝트처럼 보입니다.

그래서 ... 이것이 전부라고 생각 합니다 . 감사합니다 .



9
당신은에 대한 답변을 찾을 수 있습니다 그것은 과학 연구 코드에 대한 단위 테스트를 작성하는 가치인가? 유능한.
마크 부스

8
코드를 적극적으로 개선하려면 Code Review 에 게시하는 것이 좋습니다. 그곳의 커뮤니티가 기꺼이 도와 줄 것입니다.
hoffmale

7
"버전 관리를 사용하지 않고 새로운 반복마다 새 파일을 만들고 텍스트 파일에 어딘가에 모든 파일을 기록하는 것"과 "및"을 말하면 "또는"을 의미합니까? 버전 제어를 사용하는 경우 붙여 넣기 버전이 아닙니다. 요점은 버전 관리가 모든 이전 버전을 유지한다는 것입니다
Richard Tingle

2
@mathreadler 나는 당신이 이해하지 못한다고 생각합니다. 네, 아마도 실제로 코드를 읽고 엉망으로 만들 것입니다 (아직 알지 못하지만 다른 언어로 프로그래밍 할 수있는 사람을 가지고 있습니다). 그러나 코드는 여전히 쓰레기. 나는 나중에 그것을 읽고 내가 무엇을하고 있는지 다시 알아 내야 할 것이다. 그것은 문제, 그리고 지금은 효과가 발생하고있어 때문에 그것을 증언 할 수 있으며, I 버전 제어 및 여기에 제안 된 다른 기술을 구현 한대로 일이 쉽게되고있다.
heather

답변:


163

이것은 과학자들에게 매우 일반적인 문제입니다. 나는 그것을 많이 보았고, 항상 프로그래밍이 당신이 일을하는 도구로 측면에서 선택하는 사실에 기인합니다.

따라서 스크립트는 엉망입니다. 나는 상식에 반대하고 당신이 혼자 프로그래밍한다고 가정하면, 이것은 그렇게 나쁘지 않다고 말할 것입니다 ! 당신이 다시 쓰는 대부분의 내용을 다시는 다루지 않을 것이므로 "값"(스크립트의 결과)을 생성하는 대신 예쁜 코드를 작성하는 데 너무 많은 시간을 소비해도 큰 도움이되지 않습니다.

그러나, 당신이 한 일로 되돌아 가서 무언가가 어떻게 작동했는지 정확히 알아야 할 시간이있을 것입니다. 또한 다른 과학자가 코드를 검토해야 할 경우 모든 사람이 이해할 수 있도록 코드를 최대한 명확하고 간결하게 작성하는 것이 중요합니다.

주요 문제는 가독성이 될 것이므로 다음을 개선하기위한 몇 가지 팁이 있습니다.

변수 이름 :

과학자들은 간결한 표기법을 사용하는 것을 좋아합니다. 모든 수학 방정식은 일반적으로 단일 문자를 변수로 사용하므로 코드에서 매우 짧은 변수가 많이 나오는 것에 놀라지 않을 것입니다. 이것은 가독성을 크게 손상시킵니다. 코드로 돌아 가면 y, i 및 x2가 무엇을 나타내는 지 기억하지 못하고 그것을 알아 내려고 많은 시간을 할애합니다. 변수를 정확히 나타내는 이름을 사용하여 변수 이름을 명시 적으로 지정하십시오.

코드를 함수로 나누십시오.

이제 모든 변수의 이름을 바 꾸었으므로 방정식이 끔찍하고 여러 줄로 표시됩니다.

주 프로그램에 그대로 두지 말고 방정식을 다른 함수로 옮기고 그에 따라 이름을 지정하십시오. 이제 거대하고 혼란스러운 코드 라인을 사용하는 대신 진행 상황과 사용한 방정식을 정확하게 알려주는 간단한 지침을 제공합니다. 이것은 당신이 한 일을 알기 위해 실제 방정식을 볼 필요가 없기 때문에 메인 프로그램과 방정식 코드 자체를 개선합니다. 별도의 함수에서 원하는대로 변수 이름을 지정할 수 있습니다. 친숙한 한 글자.

이 생각의 라인에서, 무언가를 나타내는 모든 코드 조각을 찾아보십시오. 특히 무언가가 코드에서 여러 번 수행 해야하는 경우 함수로 나눕니다. 코드를 빠르게 읽을 수있게되고 더 많은 코드를 작성하지 않고도 동일한 기능을 사용할 수 있음을 알게됩니다.

케이크를 입히고 더 많은 프로그램에서 이러한 기능이 필요한 경우 라이브러리를 만들면 항상 사용할 수 있습니다.

전역 변수 :

내가 초보자 였을 때, 나는 이것이 내 프로그램의 여러 지점에서 필요한 데이터를 전달하는 좋은 방법이라고 생각했습니다. 물건을 전달하는 다른 많은 방법이 있으며, 전역 변수가하는 유일한 일은 사람들에게 두통을주는 것입니다. 프로그램의 임의의 지점으로 가면 그 값이 마지막으로 사용되거나 편집 된 시점을 알 수 없으므로 그것을 추적하는 것은 고통이 될 것입니다. 가능할 때마다 피하십시오.

함수가 여러 값을 반환하거나 수정해야하는 경우 해당 값으로 클래스를 만들고 매개 변수로 전달하거나 함수가 여러 값을 반환 (명명 된 튜플)하고 호출자 코드에서 해당 값을 할당하도록합니다.

버전 관리

이것은 가독성을 직접 향상 시키지는 않지만 위의 모든 작업을 수행하는 데 도움이됩니다. 약간의 변경을 할 때마다 버전 제어를 수행하십시오 (로컬 Git 저장소는 충분할 것입니다). 작동하지 않는 것이 있으면 변경된 것을 보거나 롤백하십시오! 이렇게하면 코드 리팩토링이 쉬워지고 실수로 물건을 깰 경우 안전망이됩니다.

이 모든 것을 염두에두면 명확하고 효과적인 코드를 작성할 수 있으며 거대한 함수와 복잡한 변수를 거치지 않아도되기 때문에 가능한 실수를 더 빨리 찾을 수 있습니다.


56
훌륭한 조언. 그러나 나는 "그다지 나쁘지 않다"는 의견을지지 할 수 없다. 너무 나쁘다. 저품질 과학 스크립트는 데이터 분석의 재현성과 분석에서 빈번한 오류의 원인이되는 큰 문제입니다. 좋은 코드를 작성하는 것은 나중에 이해할 수있을뿐만 아니라 처음부터 오류를 피할 수 있도록하는 데 유용합니다.
Jack Aidley

22
코드가 잘 알려진 수식을 구현 한 경우 단일 문자 변수 이름과 그럴 수도 있습니다. 독자에 따라, 그리고 독자가 그 이름의 의미를 이미 알고 있을지의 여부에 달려 있습니다.
cHao

11
@cHao 문제는 변수에 수식을 꽂았을 때 (따라서 함수 내에서 이름을 바꾼다) 조언이 아니라 변수 밖에서 읽고 조작 할 때와 다른 변수와 충돌하기 시작할 때 문제가된다 (예를 들어, 나는 x1, x2, x3라는 이름을 가진 세 개의 "x"변수를 필요로하는 사람들을 보았습니다)
BgrWorker

4
"나는 상식에 반대 할거야 ..."아뇨. 당신은 일반적인 교리에 반하는 우세한 교리에 반대합니다. ;) 이것은 모두 완벽하게 건전한 조언입니다.
jpmc26

3
(이전) 과학 프로그래머로서 나는 일반적으로 세 가지 규칙을 채택합니다. 비슷한 코드를 세 번 작성하면 기능이 문서화되어 별도의 모듈로 작성되고 작성됩니다 (종종 주석이지만 충분합니다). 이것은 애드혹 프로그래밍의 혼란을 제한하고 앞으로 확장 할 수있는 라이브러리를 구축 할 수있게 해줍니다.
rcollyer

141

여기 물리학 자. 거기에 있었다.

귀하의 문제는 도구 또는 프로그래밍 패러다임 (단위 테스트, OOP 등) 의 선택에 관한 것이 아니라고 주장합니다 . 그것은 관하여 태도 , 사고 방식. 변수 이름이 처음에 잘 선택되어 결국 쓰레기라는 사실이 충분히 밝혀졌습니다. 코드를 "한 번 실행 한 다음 버린다"고 생각하면 필연적으로 엉망이 될 것입니다. 그것을 공예와 사랑의 산물이라고 생각하면 아름답습니다.

깨끗한 코드를 작성하는 방법 은 단 하나 뿐이라고 생각 합니다. 코드를 실행할 사람이 아니라 코드를 읽을 사람을 위해 작성하십시오. 인터프리터는 코드가 엉망인지 신경 쓰지 않지만 인간 독자 돌보아줍니다.

당신은 과학자입니다. 과학 기사를 다듬는 데 많은 시간을 할애 할 수 있습니다. 첫 번째 초안이 복잡해 보이면 논리가 가장 자연스럽게 흐를 때까지 리팩터링합니다. 당신은 당신의 동료들이 그것을 읽고 명백한 주장을 찾길 원합니다. 당신은 학생들이 그것으로부터 배울 수 있기를 원합니다.

깨끗한 코드를 작성하는 것은 정확히 같습니다. 코드는 우연히 기계가 읽을 수있는 알고리즘에 대한 자세한 설명으로 생각하십시오. 사람들이 읽을 기사로 출판한다고 가정 해보십시오. 당신은 심지어 회의에서 그것을 보여줄 것이고 청중을 한 줄씩 살펴볼 것입니다. 이제 프레젠테이션을 연습하십시오 . 예, 한 줄씩 ! 부끄러운가? 슬라이드를 정리 (오류 ... 코드)하고 다시 연습하십시오. 결과에 만족할 때까지 반복하십시오.

리허설 후 가상의 사람들과 미래의 자아보다는 실제 사람들에게 코드를 보여줄 수 있다면 더 나을 것입니다. 한 줄씩 살펴 보는 것을“코드 워크”라고하며 어리석은 연습이 아닙니다.

물론,이 모든 것은 비용이 든다. 깨끗한 코드를 작성 하는 것은 버리기 코드를 작성하는 것보다 시간이 더 걸립니다 . 혜택 만 특정 사용 사례의 비용보다 큰지 여부 만 평가할 수 있습니다.

도구에 대해서는 중요 하지 않다고 말했습니다 . 그러나 하나를 선택해야한다면 버전 관리가 가장 유용하다고 말할 수 있습니다.


32
«깨끗한 코드를 작성하는 것은 [깨끗한 기사를 작성하는 것과] 완전히 같습니다.»나는 그것을 완전히 보증합니다.
juandesant

43
이것은 대부분의 전문 프로그래머가 말을 잊어 버리는 것입니다. 다른 프로그래머가 코드를 읽고 수정할 수있게되면 코드가 완성됩니다. 실행될 때가 아니며 올바른 출력을 생성합니다. OP는 코드를 리팩토링하고 코드를 주석 처리하여 사람이 읽을 수 있도록 스크립트 당 추가 시간을 소비해야합니다.
UEFI

31
깨끗한 코드를 작성하는 일회용 코드를 작성하는 것보다 훨씬 더 많은 시간이 걸릴 않지만, 훨씬 더 중요한 것입니다 읽기 일회용 코드하는 깨끗한 코드를 읽는 것보다 더 많은 시간이 걸립니다.
user949300

3
@UEFI 아니요, 대부분의 전문 프로그래머가 알지 못하는 것입니다. 또는 걱정하지 마십시오.
jpmc26

2
100 % 동의합니다. 통계학자는 프로그래머가 되었기 때문에 저는 직장에서 상당한 양의 '과학적'프로그래밍을합니다. 1 개월, 4 개월 또는 12 개월 후에 해당 코드로 돌아 가야 할 때 의미있는 주석이 포함 된 명확한 코드는 생명의 은인입니다. 코드를 읽으면 코드가 무엇을하고 있는지 알 수 있습니다. 주석을 읽으면 코드가 무엇을하는지 알려줍니다.
railsdog

82

버전 관리는 아마도 당신에게 돈을 가장 많이 줄 것입니다. 장기 보관 용일뿐만 아니라 단기 실험을 추적하고 작동했던 마지막 버전으로 돌아가서 메모를 남기는 데 좋습니다.

다음으로 가장 유용한 단위 테스트입니다. 단위 테스트에 관한 것은 수백만 줄의 코드가있는 코드베이스조차도 한 번에 한 기능 씩 단위 테스트됩니다. 단위 테스트는 최소 수준의 추상화에서 소규모로 수행됩니다. 이는 작은 코드 기반을 위해 작성된 단위 테스트와 큰 코드 기반을 위해 사용 된 단위 테스트간에 근본적인 차이가 없음을 의미합니다. 더 많은 것이 있습니다.

단위 테스트는 다른 것을 고칠 때 이미 작동하고 있던 것을 깨뜨 리거나 최소한 할 때 신속하게 알려주는 가장 좋은 방법입니다. 그것들은 프로그래머만큼 숙련되지 않았거나 에러를 덜 발생 시키거나보다 분명하게 만드는 더 자세한 코드를 작성하는 방법을 모르거나 모르는 경우에 실제로 유용합니다.

버전 제어와 작성 단위 테스트 사이에서 코드는 자연스럽게 훨씬 깨끗해집니다. 안정된 코딩을위한 다른 기술은 고원에 도달했을 때 배울 수 있습니다.


78
나는 종교적으로 내 코드의 대부분을 단위 테스트하지만 단위 테스트는 탐색적이고 과학적인 코드 가 쓸모없는 것보다 적다 는 것을 알았 습니다 . 방법론은 기본적으로 작동하지 않는 것 같습니다. 내 분야에서 분석 코드를 단위 테스트하는 전산 과학자를 모른다. 이 불일치의 이유가 무엇인지 확실하지 않지만 그 이유 중 하나 는 사소한 단위를 제외하고는 좋은 테스트 사례를 수립하기가 어렵거나 불가능하다는 것입니다.
Konrad Rudolph

22
@KonradRudolph 이러한 경우의 트릭은 코드에서 확실하게 정의 할 수있는 행동 (이 입력을 읽고이 값을 계산)이있는 코드의 부분들 사이에서 진정 탐구 적이거나 예를 들면 사람이 읽을 수있는 출력 또는 시각화. 문제의 분리가 불량 분리로 인해 선이 흐려져서이 상황에서 단위 테스트가 불가능하다는 인식이 생겨 반복 사이클의 시작으로 돌아갈 수 있습니다.
Ant P

18
참고로, 버전 제어는 형식이 텍스트 디핑에 적합하기 때문에 LaTeX 문서에서도 상당히 잘 작동합니다. 이런 방식으로 논문과 논문을 지원하는 코드 모두에 대한 저장소를 가질 수 있습니다. Git과 같은 분산 버전 제어를 살펴볼 것을 제안합니다. 이 학습 곡선의 비트,하지만 당신이 그것을 이해하고 나면, 당신은 당신의 개발을 반복 할 수있는 좋은 깨끗한 방법을 가지고 당신은 Github에서 같은 플랫폼을 사용하는 몇 가지 흥미로운 옵션이 학계 무료 팀 계정을 제공을 .
Dan Bryant

12
@AntP 잘 정의 된 테스트 가능한 단위로 의미있게 리팩토링 될 수있는 코드가 많지 않을 수 있습니다. 많은 과학적 코드는 본질적으로 많은 라이브러리를 함께 묶고 있습니다. 이 라이브러리는 이미 잘 테스트되고 깔끔하게 구성되어 있습니다. 즉, 저자는 "접착제"만 작성하면되며 내 경험상 타우 토믹하지 않은 접착제에 대한 단위 테스트를 작성하는 것은 거의 불가능합니다.
James_pic

7
"버전 관리와 작성 단위 테스트 사이에서 코드는 자연스럽게 훨씬 깨끗해집니다." 사실 이 아닙니다 . 개인적으로 증명할 수 있습니다. 이러한 도구 중 어느 것도 중지 엉터리 코드를 작성에서 당신을, 특히, 엉터리 코드의 상단에 엉터리 테스트를 작성하는 것은 그냥 열심히조차 청소 할 수 있습니다. 테스트는 마법의 총알이 아니며 테스트처럼 말하는 것은 여전히 ​​모든 개발자에게 배우는 끔찍한 일입니다. 그러나 버전 제어는 일반적으로 나쁜 테스트처럼 코드 자체에 손상을주지 않습니다.
jpmc26

29

(버전 제어를 사용하고 새로운 반복마다 새 파일을 만들고 텍스트 파일에 모든 파일을 기록하는 것 외에도 상황을 극적으로 도울 것입니다)

당신은 아마 이것을 스스로 알아 냈을 지 모르지만, " 어딘가에 텍스트 파일에 모든 것을 기록해야 "한다면 버전 제어 시스템을 최대한 활용하고 있지 않은 것입니다. Subversion, git 또는 Mercurial과 같은 것을 사용하고 모든 커밋마다 좋은 커밋 메시지를 작성하면 텍스트 파일의 목적을 제공하지만 저장소와 분리 할 수없는 로그가 생깁니다.

그 외에도, 버전 제어를 사용하는 것이 기존 답변에서 언급하지 않은 이유 중 하나 인 결과의 재현성으로 할 수있는 가장 중요한 일 입니다. 로그 메시지를 사용하거나 개정 번호가있는 결과에 메모를 추가 할 수 있으면 결과를 다시 생성 할 수 있으며 종이로 코드를 게시 할 수 있습니다.

더 작은 코드를 작성하려면 단위 테스트가 필요합니까? OOP는 어때요? 더 큰 프로젝트에서 작업하는 대신 "과학적 프로그래밍"을 수행 할 때 좋고 깨끗한 코드를 신속하게 작성하는 데 어떤 종류의 접근 방식이 좋습니까?

단위 테스트는 반드시 필요한 것은 아니지만 다음과 같은 경우에 유용합니다. (b) 테스트를 만들 수 있습니다. 코드로 생성하는 것이 적어도 동작에 변화 가 있는지 여부를 알려주는 회귀 테스트를 제공 할 수 있지만 이상적으로는 코드로 생성하지 않고 수동으로 예상 출력을 작성할 수 있습니다 . 테스트하는 코드보다 테스트가 버그가있을 가능성이 높은지 고려하십시오.

OOP는 도구입니다. 도움이된다면 사용하십시오. 그러나 유일한 패러다임은 아닙니다. 절차 적 프로그래밍 만 알고 있다고 가정합니다.이 경우 설명 된 컨텍스트에서 OOP보다 기능적 프로그래밍, 특히 가능한 경우 부작용을 피하는 분야를 연구하면 더 많은 이점을 얻을 것이라고 생각합니다. 파이썬은 매우 기능적인 스타일로 작성 될 수 있습니다.


4
커밋 메시지의 경우 +1; 그것들은 실제로 적용될 때 코드 버전에 묶여 있기 때문에 구식이 될 수없는 주석과 같습니다. 기존 코드를 이해하려면 오래된 주석을 읽는 것보다 프로젝트 기록을 살펴 보는 것이 더 쉽습니다 (적절한 수준으로 변경 사항이 적용되는 경우).
Silly Freak

Subversion, git 및 Mercurial은 사용할 수 없습니다. Subversion의 로컬 저장소와 함께 Git (또는 Mercurial)을 사용하는 것이 좋습니다. 솔로 코더를 사용하면 Subversion의 결함은 문제가되지 않지만 공동 개발을위한 훌륭한 도구는
아니며

2
@ mcottle, 나는 개인적으로 자식을 선호하지만, 선택이 적극적 종교 전쟁 중 하나이기 때문에 이것이 차이점에 대한 세부 정보를 얻을 수있는 적절한 장소라고 생각하지 않았습니다. OP가 지역을 겁내지 않고 무언가 를 사용하도록 장려하는 것이 좋으며, 결정은 영구적이지 않습니다.
피터 테일러

21

대학원에서는 알고리즘이 많은 코드를 직접 작성했습니다. 깨지기 쉬운 너트입니다. 정보를 대략적으로 정리하기 위해 정보를 데이터베이스에 넣고 적시에 검색 한 다음 해당 데이터를 마사지하여 사용자에게 제공하기 위해 일반적으로 모든 수학 또는 그 과정에서 알고리즘이 많은 부분. 이러한 프로그램의 경우 OOP에 대해 들어 본 모든 것, 코드를 짧은 기능으로 나누고 가능한 경우 모든 것을 한 눈에 쉽게 이해할 수 있도록하는 것이 훌륭한 조언입니다. 그러나 알고리즘이 많은 코드 또는 복잡한 수학 계산을 구현하는 코드는 거의 작동하지 않습니다.

과학적 계산을 수행하기 위해 스크립트를 작성하는 경우 사용하는 방정식 또는 알고리즘이 포함 된 논문이있을 수 있습니다. 스스로 발견 한 새로운 아이디어를 사용하고 있다면, 자신의 논문으로 아이디어를 게시 할 수 있기를 바랍니다. 이 경우 규칙은 다음과 같습니다. 코드가 게시 된 방정식과 최대한 비슷하게 읽길 원합니다. 여기에 200 가지가 넘는 지지자가있는 Software Engineering.SE에 대한 답변이이 접근 방식을 옹호하고 그 모양을 설명 합니다. 짧은 변수 이름에 대한 변명이 있습니까?

또 다른 예로서, 물리 연구 및 엔지니어링에 사용되는 물리 시뮬레이션 도구 인 Simbody 에는 훌륭한 코드 스 니펫이 있습니다 . 이 스 니펫에는 계산에 사용되는 방정식을 보여주는 주석이 있으며 가능한 한 구현되는 방정식에 가장 근접한 코드가 표시됩니다.

ContactGeometry.cpp:

// t = (-b +/- sqrt(b^2-4ac)) / 2a
// Discriminant must be nonnegative for real surfaces
// but could be slightly negative due to numerical noise.
Real sqrtd = std::sqrt(std::max(B*B - 4*A*C, Real(0)));
Vec2 t = Vec2(sqrtd - B, -sqrtd - B) / (2*A);

ContactGeometry_Sphere.cpp:

// Solve the scalar Jacobi equation
//
//        j''(s) + K(s)*j(s) = 0 ,                                     (1)
//
// where K is the Gaussian curvature and (.)' := d(.)/ds denotes differentiation
// with respect to the arc length s. Then, j is the directional sensitivity and
// we obtain the corresponding variational vector field by multiplying b*j. For
// a sphere, K = R^(-2) and the solution of equation (1) becomes
//
//        j  = R * sin(1/R * s)                                        (2)
//          j' =     cos(1/R * s) ,                                      (3)
//
// where equation (2) is the standard solution of a non-damped oscillator. Its
// period is 2*pi*R and its amplitude is R.

// Forward directional sensitivity from P to Q
Vec2 jPQ(R*sin(k * s), cos(k * s));
geod.addDirectionalSensitivityPtoQ(jPQ);

// Backwards directional sensitivity from Q to P
Vec2 jQP(R*sin(k * (L-s)), cos(k * (L-s)));
geod.addDirectionalSensitivityQtoP(jQP);

9
또한 "게시 된 방정식과 최대한 비슷하게 읽을 수있는 코드"를 만들기위한 것입니다. 죄송합니다. 길고 의미있는 변수 이름을 옹호하십시오. 과학 코드에서 가장 의미있는 이름은 종종 코드가 구현하려고하는 과학 저널에 사용 된 규칙이기 때문에 불쾌하고 짧고 잔인합니다. 저널 논문에서 발견 된 방정식을 구현하는 방정식이 많은 코드 덩어리의 경우, 논문의 명명법에 최대한 가깝게 유지하는 것이 가장 좋은 경우가 많습니다.
David Hammen

@DavidHammen : 대학원생으로서 저는 그것을 존중합니다. 프로그래머로서 나는 임시 자리 표시 자 일지라도 각 변수 의 상단에 각 변수의 의미를 일반 영어 (또는 선택한 언어)로 설명하는 거대한 주석 블록이 있다고 주장합니다 . 그런 식으로 적어도 되돌아 볼 참조가 있습니다.
tonysdg

1
@DavidHammen 게다가, 소스 파일에서 UTF-8 및 변수 이름에 대한 간단한 규칙에 대한 파이썬 지원은 쉽게 선언 할 수 있습니다 λ또는 φ추악한 대신에 lambda_phy...
마티아스 팅커

1
@tonysdg 당신은 이미 참조가 있습니다; "Hammen, et al. (2018)"(또는 무엇이든)이라고합니다. 주석 블록이 할 수있는 것보다 변수의 의미를 훨씬 자세하게 설명합니다. 변수 이름을 논문의 표기법에 가깝게 유지하는 이유는 논문의 내용과 코드의 내용을 더 쉽게 연결할 수 있기 때문입니다.
아무도

17

그래서 제 하루는 캘리포니아 대학 시스템의 연구 데이터 출판 및 보존에 있습니다. 두 사람이 재현성을 언급했으며 이것이 핵심 문제라고 생각합니다. 다른 사람이 실험을 재현하는 데 필요한 다른 방법으로 코드를 문서화하고 이상적으로는 다른 사람에게 간단하게 코드를 작성하는 것이 중요합니다 실험을 재현하고 오류 원인에 대한 결과를 확인합니다.

그러나 내가 언급하지 않았지만 중요하다고 생각하는 것은 자금 지원 기관이 점점 더 소프트웨어 출판을 데이터 출판의 일부로보고 있으며 소프트웨어 출판을 공개 과학의 요구 사항으로 만들고 있다는 것입니다.

이를 위해 일반 소프트웨어 개발자보다는 연구원을 겨냥한 특정한 것을 원한다면 Software Carpentry 조직을 충분히 추천 할 수는 없습니다 . 그들의 워크샵 중 하나에 참석할 수 있다면 좋을 것입니다 . 과학 컴퓨팅 모범 사례관한 논문을 읽는 것만으로도 시간과 접근이 가능하다면 이것도 좋습니다. 후자에서 :

과학자들은 일반적으로 상당한 도메인 별 지식이 필요하기 때문에 이러한 목적을 위해 자체 소프트웨어를 개발합니다. 그 결과, 최근의 연구에 따르면 과학자들은 일반적으로 소프트웨어 개발에 30 % 이상을 소비합니다. 그러나 이들 중 90 % 이상은 주로 독학되므로 유지 관리 가능한 코드 작성, 버전 제어 및 문제 추적기 사용, 코드 검토, 단위 테스트 및 작업 자동화와 같은 기본 소프트웨어 개발 관행에 노출되지 않습니다.

우리는 소프트웨어가 또 다른 종류의 실험 장치라고 생각하며 물리적 장치와 마찬가지로 신중하게 구축, 검사 및 사용해야합니다. 그러나 대부분의 과학자들은 실험실 및 현장 장비의 유효성을 검사하기 위해주의를 기울이고 있지만 대부분의 소프트웨어가 얼마나 안정적인지 모릅니다. 이로 인해 출판 된 연구의 중심 결론에 영향을 미치는 심각한 오류가 발생할 수 있습니다. …

또한 소프트웨어는 종종 하나 이상의 프로젝트에 사용되며 다른 과학자들에 의해 재사용되기 때문에 컴퓨팅 오류는 과학적 프로세스에 불균형 한 영향을 줄 수 있습니다. 이러한 유형의 계단식 영향으로 인해 게시 후까지 다른 그룹 코드의 오류가 발견되지 않은 경우 몇 가지 중요한 철회가 발생했습니다.

그들이 권장하는 관행에 대한 높은 수준의 개요 :

  1. 컴퓨터가 아닌 사람을위한 프로그램 작성
  2. 컴퓨터가 일을하게하십시오
  3. 증분 변경
  4. 자신이나 다른 사람을 반복하지 마십시오
  5. 실수 계획
  6. 제대로 작동 한 후에 만 ​​소프트웨어 최적화
  7. 기계 설계가 아닌 문서 디자인 및 목적
  8. 공동 작업

논문은 이러한 각 점에 대해 상당히 자세하게 설명합니다.


16

일부 표준 작업을 수행 할 수 있고 작성 속도가 훨씬 빠르며 프로그램의 부족으로 인해 비슷한 수준의 가독성 인 OOP라고하는 코드를 작성하는 것이 실제로 의미가 있습니까?

개인적 답변 :
저는 과학적인 목적으로도 많은 스크립트를 작성합니다. 더 작은 스크립트의 경우, 나는 일반적인 좋은 프로그래밍 실습을 따르려고합니다 (예 : 버전 제어 사용, 변수 이름으로 자체 제어 연습). 데이터 세트를 빠르게 열거 나 시각화하기 위해 무언가를 쓰고 있다면 OOP를 신경 쓰지 않습니다.

일반적인 답변 :
"그것은 달려 있습니다." 그러나 프로그래밍 개념이나 패러다임을 언제 사용해야할지 고민하고 있다면 몇 가지 고려해야 할 사항이 있습니다.

  • 확장 성 : 스크립트가 단독으로 실행됩니까, 아니면 더 큰 프로그램에서 사용됩니까? 그렇다면 OOP를 사용하는 더 큰 프로그래밍입니까? 스크립트의 코드를 더 큰 프로그램에 쉽게 통합 할 수 있습니까?
  • 모듈성 : 일반적으로 코드는 모듈 식이어야합니다. 그러나 OOP는 코드를 매우 특별한 방식으로 청크로 나눕니다. 이러한 유형의 모듈성 (예 : 스크립트를 클래스로 나누는 것)이 현재 수행중인 작업에 적합합니까?

작고 빠른 프로젝트에서 "다시 시작"하고 깨끗하게 프로그래밍하는 방법을 알고 싶습니다.

# 1 : 기존의 내용에 익숙해 지십시오.
"단순한"스크립팅 (그리고 실제로 과학 구성 요소 만 신경 쓰지만)이지만 다른 프로그래밍 개념과 패러다임에 대해 배우려면 약간의 시간이 걸립니다. 그렇게하면 무엇을 사용하고 싶지 않아야하는지, 언제 사용하지 않아야하는지 더 잘 알 수 있습니다. 약간 힘들 것 같습니다. 그리고 당신은 여전히 ​​"어디에서 시작을 시작합니까?"라는 질문을받을 수 있습니다. 다음 두 글 머리에서 좋은 출발점을 설명하려고 노력합니다.

# 2 : 당신이 아는 것을 고치기 시작하십시오 :
개인적으로, 나는 내가 아는 것부터 시작합니다. 일부 버전 관리를 통해 변수 이름으로 더 잘 나아갈 수 있도록 훈련을 시작하십시오 (심각한 어려움). 당신이 알고있는 것을 잘못 고치면 분명하게 들릴 수 있습니다. 그러나 내 경험상 한 가지를 고치면 다른 것으로 이어질 수 있습니다. 내가 알기 전에, 내가 잘못하고있는 10 가지 일을 발표하고 문제를 해결하는 방법이나 깨끗한 방법으로 구현하는 방법을 알아 냈습니다.

# 3 : 프로그래밍 파트너 확보 :
"다시 시작"하는 데 공식적인 수업을 수강하지 않는 경우 개발자와 팀을 이루어 코드를 검토하도록 요청하십시오. 그들이하는 일의 과학 부분을 이해하지 못하더라도 코드를 더 우아하게 만들기 위해 무엇을 할 수 있었는지 말할 수있을 것입니다.

# 4 : 컨소시엄 찾기 :
과학 분야가 무엇인지 모르겠습니다. 그러나 과학 분야에서하는 일에 따라 컨소시엄, 실무 그룹 또는 회의 참가자를 찾아보십시오. 그런 다음 작업중인 표준이 있는지 확인하십시오. 코딩 표준으로 이어질 수 있습니다. 예를 들어, 나는 많은 지리 공간 작업을합니다. 회의 논문과 실무 그룹을 살펴본 결과 Open Geospatial Consortium이되었습니다 . 그들이하는 것 중 하나는 지리 공간 개발 표준에 관한 작업입니다.

도움이 되길 바랍니다.


참고 : 방금 OOP를 예로 사용했습니다. OOP를 사용하여 코드 작성을 처리하는 방법에 갇혀 있다고 생각하지 않기를 바랍니다. 그 예를 계속해서 답을 작성하는 것이 더 쉬웠습니다.


# 3이 가장 중요한 문제라고 생각합니다. 숙련 된 프로그래머는 OP에게 필요한 개념 (# 1), 스크립트를 더 나은 방식으로 구성하는 방법 및 버전 제어 (# 2)를 사용하는 방법을 알려줄 수 있습니다.
Doc Brown

16

유닉스 원칙을 고수하는 것이 좋습니다. 간단하게 유지하십시오. (키스)

또는 다른 방법을 사용하십시오. 한 번에 한 가지만 수행하고 잘 수행하십시오.

그게 무슨 뜻이야? 우선, 그것은 당신의 기능이 짧아야 함을 의미합니다. 몇 초 내에 목적, 사용법 및 구현에서 완전히 이해할 수없는 기능은 너무 길다. 한 번에 여러 가지 작업을 수행 할 수 있으며 각 작업은 자체 기능이어야합니다. 그래서 나누십시오.

코드 라인의 관점에서 볼 때 휴리스틱은 10 라인이 좋은 기능이며 20을 초과하는 것은 쓰레기 일 가능성이 큽니다. 다른 사람들에게는 다른 휴리스틱이 있습니다. 중요한 부분은 실제로 순간적으로 파악할 수있는 길이를 유지하는 것입니다.

긴 기능을 어떻게 분할합니까? 먼저 반복되는 코드 패턴을 찾으십시오. 그런 다음 이러한 코드 패턴 을 고려 하여 설명적인 이름을 지정하고 코드 축소를보십시오 . 실제로 가장 좋은 리팩토링은 코드 크기를 줄이는 리팩토링입니다.

해당 기능이 복사 붙여 넣기로 프로그래밍 된 경우 특히 그렇습니다. 반복되는 패턴을 볼 때마다 이것이 자체 기능으로 바뀌어야한다는 것을 즉시 알 수 있습니다. 이것이 자신을 반복하지 말 것 (DRY) 의 원칙입니다 . 복사-붙여 넣기를 할 때마다 무언가 잘못되고 있습니다! 대신 함수를 작성하십시오.

일화는
한 달에 약 500 줄의 기능을 가진 코드를 리팩토링하는 데 몇 달을 보냈습니다. 내가 완료 한 후, 총 코드는 약 1000 줄 짧았습니다. 코드 줄 측면에서 부정적인 출력을 생성했습니다. 회사에 빚을졌습니다 ( http://www.geekherocomic.com/2008/10/09/programmers-salary-policy/index.html ). 아직도, 나는 이것이 내가 한 것 중 가장 소중한 작품 중 하나라고 굳게 믿는다 ...

일부 기능은 서로 다른 여러 가지 작업을 수행하기 때문에 길어질 수 있습니다. 이는 DRY 위반이 아니지만 분할 될 수도 있습니다. 결과는 종종 원래 기능의 개별 단계를 구현하는 여러 기능을 호출하는 고급 기능입니다. 일반적으로 코드 크기가 커지지 만 추가 된 함수 이름은 코드를 더 읽기 쉽게 만드는 데 효과적입니다. 이제 모든 단계가 명시 적으로 명명 된 최상위 함수가 있으므로 또한이 분할 후 어느 단계가 어떤 데이터에서 작동하는지가 분명합니다. (함수 인수. 전역 변수를 사용하지 않습니까?)

이런 종류의 부분 함수 분할에 대한 좋은 휴리스틱은 섹션 주석을 작성하려고 할 때마다 또는 코드에서 섹션 주석을 찾을 때입니다. 이것은 기능을 분리해야 할 지점 중 하나 일 가능성이 높습니다. 섹션 주석은 또한 새로운 기능의 이름을 고무시키는 역할을 할 수 있습니다.

KISS 및 DRY 원칙은 먼 길을 걸을 수 있습니다. OOP 등을 즉시 시작할 필요는 없으며 종종이 두 가지만 적용하면 크게 단순화 할 수 있습니다. 그러나 장기적으로 OOP 및 기타 패러다임에 대해 알면 프로그램 코드를보다 명확하게 만드는 데 사용할 수있는 추가 도구를 제공하기 때문에 이익을 얻습니다.

마지막으로 커밋으로 모든 작업을 기록하십시오. 당신은 무언가를 새로운 함수, 즉 commit 입니다. 당신은 그들이 정말 같은 일을하기 때문에, 하나에 두 가지 기능을 융합 하는이 커밋이다 . 변수 이름을 바꾸면 커밋 입니다. 자주 커밋하십시오. 하루가 지나도 커밋하지 않으면 뭔가 잘못되었을 수 있습니다.


2
긴 방법을 나누는 것에 대한 좋은 점. 일화 후 첫 번째 단락에 대한 또 다른 좋은 휴리스틱 : 방법을 논리적으로 섹션으로 나눌 수 있고 각 섹션의 기능을 설명하는 주석을 작성하려는 경우 주석에서 분리해야합니다. 좋은 소식은, 그 의견은 아마도 새로운 방법을 무엇이라고 부르는지에 대한 좋은 아이디어를 줄 것입니다.
Jaquez

@Jaquez Ah, 완전히 잊어 버렸습니다. 상기시켜 주셔서 감사합니다. 나는 이것을 포함하도록 내 대답을 업데이트했습니다 :-)
cmaster

1
좋은 점은 "DRY"가 가장 중요한 단일 요소라고 말하기 위해 이것을 단순화하고 싶습니다. "반복"을 식별하고 제거하는 것은 거의 모든 다른 프로그래밍 구성의 초석입니다. 달리 말하면, 모든 프로그래밍 구성은 적어도 부분적으로 DRY 코드를 작성하는 데 도움이됩니다. "No Duplication Ever"라고 말한 다음 식별하고 제거하는 연습을하십시오. 비슷한 코드가 아니더라도 기능을 복제하는 것일 수 있습니다.
Bill K

11

나는 버전 관리가 많은 문제를 즉시 해결할 것이라는 다른 사람들의 의견에 동의합니다. 구체적으로 :

  • 버전 관리가 수행하는 작업이므로 변경 내용이나 파일 사본이 많은 목록을 유지할 필요가 없습니다.
  • 덮어 쓰기 등으로 인해 더 이상 파일이 손실되지 않습니다 (기본 사항 만 고수하는 한 "예 :"기록 다시 작성 "방지)
  • 쓸모없는 주석, 데드 코드 등이 "경우에 따라"유지 될 필요가 없습니다. 일단 버전 관리에 전념하면 자유롭게 핵무기를 만들 수 있습니다. 이것은 매우 해방감을 느낄 수 있습니다!

나는 그것을 너무 생각하지 말고 : git 만 사용하십시오. 간단한 명령 (예 : 단일 master브랜치)을 고수하고 아마도 GUI를 사용하면 좋을 것입니다. 보너스로 무료 게시 및 백업을 위해 gitlab, github 등을 사용할 수 있습니다.)

이 답변을 작성한 이유는 위에서 언급하지 않은 두 가지 시도를 해결하기 위해서였습니다. 첫 번째는 어설 션 을 단위 테스트의 간단한 대안으로 사용 하는 것입니다. 단위 테스트는 함수 / 모듈 / 테스트 대상을 "외부"로 배치하는 경향이 있습니다. 일반적으로 일부 데이터를 함수로 보내고 결과를 다시 수신 한 다음 해당 결과의 일부 속성을 확인합니다. 이것은 일반적으로 좋은 생각이지만 몇 가지 이유로 불편할 수 있습니다 (특히 "쓰러 뜨리기"코드).

  • 단위 테스트는 함수에 제공 할 데이터를 결정해야합니다. 그 데이터는 현실적이어야하며 (그렇지 않으면 테스트 할 점이 거의 없음) 올바른 형식을 가져야합니다.
  • 단위 테스트는 그들이 주장하고 싶은 것에 "접근"해야합니다. 특히, 단위 테스트는 함수 내부의 중간 데이터를 확인할 수 없습니다. 우리는 그 기능을 더 작은 조각으로 나누고, 조각들을 테스트하고, 다른 곳에 함께 연결해야합니다.
  • 단위 테스트는 프로그램과 관련이 있다고 가정합니다. 예를 들어, 테스트 스위트는 마지막으로 실행 된 이후에 큰 변화가 있었으면 더 이상 사용되지 않는 코드에 대한 테스트가있을 수 있습니다.

어설 션에는 프로그램의 정상적인 실행 중에 확인되기 때문에 이러한 단점이 없습니다. 특히:

  • 그것들은 정상적인 프로그램 실행의 일부로 실행되기 때문에 실제로 실제 데이터를 가지고 있습니다. 별도의 큐 레이션이 필요하지 않으며 정의에 따라 현실적이고 올바른 형식을 갖습니다.
  • 어설 션은 코드의 어느 곳에서나 작성할 수 있으므로 확인하려는 데이터에 액세스 할 수있는 곳이면 어디든 지정할 수 있습니다. 함수에서 중간 값을 테스트하려면 해당 함수의 중간에 어설 션을 추가하면됩니다.
  • 인라인으로 작성 되었기 때문에 어설 션은 코드 구조와 "동기화되지 않을"수 없습니다. 기본적으로 어설 션이 선택되어 있는지 확인하면 다음에 프로그램을 실행할 때 전달되는지 여부를 즉시 확인할 수 있으므로 "stale"에 대해 걱정할 필요가 없습니다!

속도를 요인으로 언급하면 해당 루프에서 어설 션 검사가 바람직하지 않을 수 있지만 설정 및 후속 처리를 검사하는 데 여전히 유용합니다. 그러나 거의 모든 어설 션 구현은이를 해제 할 수있는 방법을 제공합니다. 예를 들어 파이썬 에서는 -O옵션 으로 실행하여 분명히 비활성화 할 수 있습니다 (이전에는 어설 션을 비활성화 할 필요가 없었기 때문에 이것을 알지 못했습니다). 당신이 그들을 두는 것이 내가 추천 기본적으로; 코딩 / 디버깅 / 테스트주기가 느려지는 경우 데이터의 작은 하위 집합을 사용하여 테스트하거나 테스트하는 동안 시뮬레이션을 반복하는 횟수 등을 수행하는 것이 좋습니다. 성능상의 이유로 테스트가 아닌 실행에서 어설 션을 비활성화하면 먼저 권장 사항 이 실제로 속도 저하의 원인인지 측정 하는 것입니다. (성능 병목 현상에 관해서는 자신을 속이기 쉽습니다.)

마지막 조언은 종속성을 관리하는 빌드 시스템을 사용하는 것입니다. 개인적으로 Nix 를 사용 하지만 Guix대해서도 좋은 소식을 들었습니다 . Docker와 같은 대안도 있습니다.이 방법은 과학적 관점에서 훨씬 유용하지는 않지만 조금 더 친숙합니다.

Nix와 같은 시스템은 최근에 (약간) 인기를 얻었으며 일부는 사용자가 설명하는 것처럼 "throw away"코드에 대해 과도하다고 생각할 수도 있지만 과학 컴퓨팅의 재현성에 대한 이점은 엄청납니다. 다음과 같이 실험을 실행하기위한 쉘 스크립트를 고려하십시오 (예 :) run.sh.

#!/usr/bin/env bash
set -e
make all
./analyse < ./dataset > output.csv

대신 다음과 같이 Nix "파생"으로 다시 작성할 수 있습니다 (예 :) run.nix.

with import <nixpkgs> {};
runCommand "output.csv" {} ''
  cp -a ${./.} src
  cd src
  make all
  ./analyse < ./dataset > $out
''

그 사이 의 내용은 다른 문자열의 내용에이를 연결하는 데 사용할 수 있다는 ''...''점을 제외하고는 이전과 동일하게 bash 코드입니다 (이 경우을 포함하는 디렉토리의 경로로 확장됩니다 ). 이 라인 은 bash 코드 실행 을 제공하는 Nix의 표준 라이브러리를 가져옵니다 . 우리가 사용하는 우리의 실험을 실행할 수 있습니다 와 같은 경로를 줄 것이다 .${...}./.run.nixwith import ...runCommandnix-build run.nix/nix/store/1wv437qdjg6j171gjanj5fvg5kxc828p-output.csv

이게 우리를 어떻게 사나요? Nix는 자동으로 "깨끗한"환경을 설정하며, 명시 적으로 요청한 항목에만 액세스 할 수 있습니다. 특히, $HOME우리가 설치 한 시스템 소프트웨어 와 같은 변수에 접근 할 수 없습니다 . 이것은 ~/.config우리가 설치 한 프로그램 의 내용 이나 버전 과 같은 현재 기계의 세부 사항과는 독립적 인 결과를 만듭니다 . AKA는 다른 사람들이 우리의 결과를 복제하지 못하게하는 것들입니다! 이것이 내가 추가 한 이유입니다cp기본적으로 프로젝트에 액세스 할 수 없으므로 명령을 실행하십시오. 시스템의 소프트웨어가 Nix 스크립트에서 사용 가능하지 않다는 것은 성가신 것처럼 보일 수도 있지만, 다른 방식으로도 진행됩니다. 스크립트에서 시스템을 사용하기 위해 시스템에 Nix 이외의 다른 시스템을 설치할 필요는 없습니다. 우리는 그냥 요청하면 Nix는 꺼지고 가져 오기 / 컴파일 / 필요한 것은 무엇이든 (대부분은 바이너리로 다운로드되며 표준 라이브러리도 엄청납니다!) 예를 들어, 특정 언어 버전의 특정 Python 및 Haskell 패키지와 다른 정크 파일을 원할 경우 (왜 그렇지 않습니까?)

with import <nixpkgs> {};
runCommand "output.csv"
  {
    buildInputs = [
      gcc49 libjson zlib
      haskell.packages.ghc802.pandoc
      (python34.withPackages (pyPkgs: [
        pyPkgs.beautifulsoup4 pyPkgs.numpy pyPkgs.scipy
        pyPkgs.tensorflowWithoutCuda
      ]))
    ];
  }
  ''
    cp -a ${./.} src
    cd src
    make all
    ./analyse < ./dataset > $out
  ''

동일한 방법 nix-build run.nix으로 먼저 요청한 모든 것을 가져오고 나중에 원하는 경우 모두 캐싱합니다. 출력 (이라고하는 모든 파일 / 디렉토리 $out)은 Nix에 의해 저장되며, 이는 튀어 나오는 경로입니다. 요청한 모든 입력 (스크립트 내용, 다른 패키지, 이름, 컴파일러 플래그 등)의 암호화 해시로 식별됩니다. 그 다른 패키지의 해시에 의해 식별됩니다 그들의 입력하고, 그래서 우리는 곧 다시 등 떠들썩한 파티를 컴파일하고, GCC의 버전을 컴파일 된 GCC의 버전으로, 모든 것을 provinence의 전체 체인을 갖도록에!

잘만되면 이것이 우리에게 과학 코드를 많이 사는데, 시작하기가 상당히 쉽다는 것을 보여주었습니다. 또한 과학자들에 의해 매우 심각하게 얻을 시작하고있다, 예를 들어 (Google 최고 히트) https://dl.acm.org/citation.cfm?id=2830172 때문에 (단지 프로그래밍 등) 육성하기 위해 유용한 기술이 될 수 있습니다


2
매우 자세한 유용한 답변-나는 다른 답변을 정말 좋아하지만 어설 션은 매우 유용한 첫 단계처럼 들립니다.
heather

9

본격적인 버전 관리 + 패키징 + 단위 테스트 종류의 사고 방식 (어느 시점에서 달성 해야하는 좋은 프로그래밍 관행)에 가지 않고, 내가 생각할만한 중간 솔루션 중 하나는 Jupiter Notebook 을 사용하는 것 입니다. 이것은 과학적 계산과 더 잘 통합되는 것 같습니다.

생각을 코드와 혼합 할 수 있다는 장점이 있습니다. 접근 방식이 다른 접근 방식보다 나은 이유를 설명하고 임시 섹션에 기존 코드를 그대로 둡니다. 셀을 올바르게 사용하는 것 외에도 자연스럽게 코드를 조각화하고 이해를 도울 수있는 함수로 구성 할 수 있습니다.


1
또한 이것은 재현성에 실제로 도움이됩니다. 예를 들어 정확히 같은 코드를 실행하여 출판물 그림을 생성하거나 몇 달 전에 검토 자 의견을 통합하기 위해 삭제 한 항목으로 돌아갈 수 있습니다.
afaulconbridge

더 많은 것을 읽고 싶은 사람은 이것을 문맹 프로그래밍이라고도합니다.
llrs

6

최고의 답변은 이미 훌륭하지만 귀하의 질문 중 일부를 직접 처리하고 싶었습니다.

더 작은 코드를 작성하려면 단위 테스트가 필요합니까?

코드의 크기는 단위 테스트의 필요성과 직접 관련이 없습니다. 단위 코드 는 복잡한 코드베이스 에서 더 가치가 있으며 작은 코드베이스는 일반적으로 큰 코드베이스만큼 복잡하지 않습니다.

단위 테스트는 실수하기 쉬운 코드 나이 코드를 많이 구현할 때 코드에 적합합니다. 단위 테스트는 현재 개발 에 도움이 되지 않지만 향후 실수로 인해 기존 코드가 갑자기 오작동 하게 만드는 실수를 방지하기 위해 많은 노력을 기울입니다.

라이브러리 A가 숫자의 제곱을 수행하는 응용 프로그램이 있고 라이브러리 B가 피타고라스 정리를 적용한다고 가정 해 봅시다. 분명히 B는 A에 의존합니다. 라이브러리 A에서 무언가를 고쳐야하며, 숫자를 제곱하는 대신 큐브를 만드는 버그를 소개한다고 가정 해 봅시다.

라이브러리 B는 갑자기 오작동을 일으켜 예외를 던지거나 단순히 잘못된 출력을 줄 수 있습니다. 그리고 라이브러리 B의 버전 기록을 보면, 그대로 유지됩니다. 문제의 최종 결과는 무엇이 잘못 될 수 있는지에 대한 표시가 없으며 문제가 A에 있음을 깨닫기 전에 B의 동작을 디버깅해야한다는 것입니다. 그것은 낭비되는 노력입니다.

단위 테스트를 입력하십시오. 이 테스트는 라이브러리 A가 의도 한대로 작동하는지 확인합니다. 라이브러리 A에 버그가 발생하여 잘못된 결과를 반환하면 단위 테스트에서이를 잡아냅니다. 따라서 라이브러리 B를 디버깅하려고 시도하지 않아도됩니다.
이는 범위를 벗어 났지만 지속적인 통합 개발에서는 누군가가 코드를 커밋 할 때마다 단위 테스트가 실행되므로 최대한 빨리 무언가를 파산했음을 알 수 있습니다.

특히 복잡한 수학 연산의 경우 단위 테스트가 도움이 될 수 있습니다. 몇 가지 예제 계산을 수행 한 다음 계산 된 출력과 실제 출력 (동일한 입력 매개 변수 기반)을 비교 한 단위 테스트를 작성합니다.

그러나 단위 테스트는 좋은 코드 를 만드는 데 도움이되지 않고 유지 관리 하는 데 도움이 됩니다. 일반적으로 코드를 한 번 작성하고 다시 방문하지 않으면 단위 테스트의 효과가 떨어집니다.

OOP는 어때요?

OOP는 다음과 같이 별개의 엔티티를 생각하는 방법입니다.

A는 때 Customer를 구입하고 싶어 Product, 그는 회담 Vendor를받을 Order. Accountant의 뜻은 다음을 지불 Vendor.

기능 프로그래머가 사물에 대해 어떻게 생각하는지 비교하십시오.

고객이하고자 할 때 purchaseProduct(), 그는 talktoVendor()그래서 그들은 것입니다 sendOrder()그합니다. 그러면 회계사가됩니다 payVendor().

사과와 오렌지. 둘 중 어느 것도 다른 것보다 객관적으로 나아지지 않습니다. 주목해야 할 한 가지 흥미로운 점은 OOP에 대해 Vendor두 번 언급되었지만 동일한 것을 나타냅니다. 그러나 기능적인 프로그래밍, talktoVendor()그리고 payVendor()별도의 두 가지가 있습니다.
이것은 접근 방식의 차이점을 보여줍니다. 이 두 작업간에 공유 공급 업체별 논리가 많으면 OOP가 코드 중복을 줄이는 데 도움이됩니다. 그러나 둘 사이에 공유 된 논리 Vendor가없는 경우 단일 논리로 병합하는 것은 무의미한 작업이므로 fuctional 프로그래밍이 더 효율적입니다.

종종 수학 계산과 과학 계산은 암시 적 공유 논리 / 수식에 의존하지 않는 별개의 연산입니다. 따라서 기능 프로그래밍은 OOP보다 더 자주 사용됩니다.

더 큰 프로젝트에서 작업하는 대신 "과학적 프로그래밍"을 수행 할 때 좋고 깨끗한 코드를 신속하게 작성하는 데 어떤 종류의 접근 방식이 좋습니까?

귀하의 질문은 과학적 프로그래밍을 수행하든 더 큰 (나는 당신이 엔터프라이즈를 의미한다고 생각합니다) 프로젝트에서 작업하든 "좋은 코드"의 정의가 변경된다는 것을 암시합니다.

좋은 코드의 정의는 바뀌지 않습니다. 필요가 복잡성을 피하기 위해 (깨끗한 코드를 작성하여 수행 할 수 있습니다)하지만, 변화 않습니다.

같은 주장이 다시 여기에 온다.

  • 이전 코드를 다시 방문하지 않고 논리를 분할하지 않고도 논리를 완전히 이해 한 경우 유지 관리하기 위해 과도한 노력을 기울이지 마십시오.
  • 이전 코드를 다시 방문하거나 필요한 논리가 너무 복잡하여 한 번에 모두 처리 할 수 ​​없으므로 (솔루션을 구획화해야 함) 깨끗하고 재사용 가능한 닫기 작성에 집중하십시오.

나는 종종 프로그래밍 자체가 그렇게 복잡하지 않기 때문에 이러한 질문을한다. 프로그래밍으로 테스트하거나 연구하는 것은 수학이나 과학에 관한 것입니다.

나는 당신이 여기에서 만드는 구별을 얻지 만, 기존 코드를 되돌아 볼 때 수학과 프로그래밍을 모두보고 있습니다. 경우 중 하나가 인위적인 또는 복잡, 당신은 그것을 읽을 어려움을 겪고 있습니다.

예를 들어, 두 변수와 함수가 아마 그것을 처리 할 수있을 때 클래스가 필요한가?

OOP 원칙을 제외하고 몇 가지 데이터 값을 저장하기 위해 클래스를 작성하는 주된 이유는 메서드 매개 변수 선언 및 반환 값을 단순화 하기 때문 입니다. 예를 들어 위치 (위도 / 경도 쌍)를 사용하는 방법 float latitude, float longitude이 많으면 입력 하는 데 지쳐서 작성하는 것이 훨씬 Location loc좋습니다.

메소드가 일반적으로 하나의 값을 리턴한다고 생각할 때 (언어 별 기능이 더 많은 값을 리턴하지 않는 한) 위치와 같은 것이 두 개의 값 (lat + lon)을 리턴하기를 원할 때 더욱 복잡해집니다. 이렇게하면 Location코드를 단순화 하는 클래스 를 만들 수 있습니다.

예를 들어, 두 변수와 함수가 아마 그것을 처리 할 수있을 때 클래스가 필요한가?

주목할 또 다른 흥미로운 점은 데이터 값과 방법을 혼합하지 않고도 OOP를 사용할 수 있다는 것입니다. 모든 개발자가 여기에 동의하지는 않지만 (일부 반 패턴이라고 함) 별도의 데이터 클래스 (저장소 값 필드)와 논리 클래스 (저장소 메서드) 가있는 빈혈 데이터 모델을 가질 수 있습니다 .
이것은 물론 스펙트럼에 있습니다. 당신은 완벽하게 빈혈 일 필요는 없습니다. yu는 적절하다고 생각할 때 사용할 수 있습니다.

예를 들어, 사람의 이름과 성을 단순히 연결하는 방법은 Person실제로 "논리적"이 아니라 계산 된 값이기 때문에 클래스 자체에 보관 될 수 있습니다 .

(이것은 일반적으로 프로그램의 속도가 더 빠른쪽에있는 것이 바람직한 상황이라고 생각합니다. 시뮬레이션의 25,000,000 회 이상의 시간 단계를 실행할 때는 다소 필요합니다.)

클래스는 항상 필드의 합계만큼 큽니다. Location두 개의 float값으로 구성된 예를 다시 살펴보면 단일 Location객체가 두 개의 개별 float값 만큼 많은 메모리를 차지 한다는 점에 유의해야 합니다.

그런 의미에서 OOP를 사용하는지 여부는 중요하지 않습니다. 메모리 풋 프린트는 동일합니다.

성능 자체도 큰 장애물이 아닙니다. 예를 들어 전역 메소드 또는 클래스 메소드 사용의 차이점은 런타임 성능과 관련이 없지만 바이트 코드의 컴파일 타임 생성과 관련이 있습니다.

케이크 레시피를 영어로 작성하든 스페인어로 작성하든 케이크를 굽는 데 30 분이 걸린다는 사실은 변경되지 않습니다 (= 런타임 성능). 레시피의 언어가 변경되는 유일한 것은 요리사가 재료를 혼합하는 방법입니다 (= 바이트 코드 컴파일).

파이썬의 경우 코드를 호출하기 전에 코드를 명시 적으로 사전 컴파일 할 필요가 없습니다. 그러나 사전 컴파일하지 않으면 코드를 실행하려고 할 때 컴파일이 발생합니다. "런타임"이라고 말하면 실행을 선행 할 수있는 컴파일이 아니라 실행 자체를 의미합니다.


6

깨끗한 과학 코드의 장점

  • ... 프로그래밍 서적을 보면 종종 더 큰 프로젝트에서 다루어지는 것 같습니다.

  • ... 일부 표준 작업을 수행 할 수 있고 작성 속도가 훨씬 빠르며 프로그램이 부족하여 비슷한 수준의 가독성이되었을 때 OOP라고하는 코드를 작성하는 것이 실제로 의미가 있습니까?

향후 코더의 관점에서 코드를 고려하는 것이 도움이 될 수 있습니다.

  • 그들은 왜이 파일을 열었습니까?
  • 그들은 무엇을 찾고 있습니까?

내 경험으로는

깨끗한 코드로 결과를 쉽게 확인할 수 있어야합니다.

  • 사용자가 프로그램을 실행하기 위해 무엇을해야하는지 쉽게 알 수 있습니다.
  • 개별 알고리즘을 개별적으로 벤치마킹 할 수 있도록 프로그램을 분할 할 수 있습니다.

  • 하나의 관련없는 작업으로 인해 다른 작업이 다르게 작동하는 반 직관적 인 부작용이있는 함수를 작성하지 마십시오. 이를 피할 수 없으면 코드에 필요한 내용과 설정 방법을 문서화하십시오.

깨끗한 코드는 미래의 코더를위한 예제 코드 역할을 할 수 있습니다

명확한 주석 (함수 호출 방법을 보여주는 주석 포함)과 잘 분리 된 기능은 누군가가 막 시작한 (또는 미래에) 작업에서 유용한 정보를 만드는 데 걸리는 시간을 크게 변화시킬 수 있습니다.

이 외에도, 다른 사람이 사용할 수 있도록 스크립트를 실제 라이브러리로 만들려는 경우 알고리즘에 실제 "API"를 작성하면 더 잘 준비 할 수 있습니다.

추천

주석을 사용하여 수학 공식을 인용하십시오.

  • 특히 최적화 (trig identity, Taylor series 등)를 사용한 경우 수학 공식을 인용하기 위해 주석을 추가하십시오.
  • 책에서 수식을 얻은 John Smith Method from Some Book 1st Ed. Section 1.2.3 Pg 180경우 웹 사이트 나 종이에서 수식을 찾은 경우 라는 주석을 추가하십시오 .
  • '링크 만'댓글을 피하는 것이 좋습니다. 사람들이 Google에 액세스 할 수 있도록 이름으로 방법을 참조해야합니다. 이전 내부 페이지로 리디렉션되는 '링크 만'댓글이 표시되어 매우 실망 할 수 있습니다. .
  • 유니 코드 / ASCII로 여전히 읽기 쉬운 경우 주석에 수식을 입력 할 수 있지만 매우 어색해질 수 있습니다 (코드 주석은 LaTeX가 아닙니다).

의견을 현명하게 사용하십시오

좋은 변수 이름 / 함수 이름을 사용하여 코드의 가독성을 향상시킬 수 있다면 먼저 수행하십시오. 주석을 제거 할 때까지 주석이 영구적으로 표시되므로 최신이 아닌 주석을 작성하십시오.

설명 변수 이름 사용

  • 단일 문자 변수가 수식의 일부인 경우 가장 좋은 옵션 일 수 있습니다.
  • 미래의 독자가 작성한 코드를보고 구현중인 방정식과 비교하는 것이 중요 할 수 있습니다.
  • 적절한 경우 접미사를 추가하여 실제 의미를 설명합니다 (예 : xBar_AverageVelocity
  • 앞에서 언급했듯이 주석에 이름으로 사용중인 수식 / 방법을 명확하게 표시하는 것이 좋습니다.

알려진 좋고 나쁜 데이터에 대해 프로그램을 실행하는 코드를 작성하십시오.

더 작은 코드를 작성하려면 단위 테스트가 필요합니까?

나는 단위 테스트가 도움이 될 수 있다고 생각합니다. 과학 코드에 대한 최상의 단위 테스트 형태는 알려진 나쁜 데이터에서 실행되는 일련의 테스트라고 생각합니다.

알고리즘을 실행하는 코드를 작성하고 결과가 예상 한 것과 얼마나 다른지 확인하십시오. 이렇게하면 실수로 잘못된 긍정 결과를 야기하는 무언가를 하드 코딩하거나 실수로 함수가 항상 같은 값을 반환하도록하는 문제를 찾아 낼 수 있습니다.

이는 모든 추상화 수준에서 수행 할 수 있습니다. 예를 들어 전체 패턴 일치 알고리즘을 테스트하거나 최적화 프로세스에서 두 결과 사이의 거리를 계산하는 함수를 테스트 할 수 있습니다. 먼저 결과에 가장 중요한 영역 및 / 또는 가장 중요한 코드 부분으로 시작하십시오.

새로운 테스트 사례를 쉽게 추가하고 "헬퍼"기능 추가를 고려하고 입력 데이터를 효과적으로 구성하십시오. 이는 입력 데이터를 파일로 저장하여 테스트를 쉽게 다시 실행할 수 있도록하는 데 도움이 될 수 있지만 오 탐지 나 편견 / 사소하게 해결 된 테스트 사례를 피하는 데 매우주의해야합니다.

같은 것을 사용을 고려 교차 검증 을 참조 검증 십자가에이 게시물에 대한 자세한 내용입니다.

버전 관리 사용

버전 제어를 사용하고 외부 사이트에서 저장소를 호스팅하는 것이 좋습니다. 무료로 리포지토리를 호스팅 할 사이트가 있습니다.

장점 :

  1. 하드 디스크 고장시 백업 제공
  2. 기록을 제공하여 최근에 발생한 문제가 실수로 파일을 변경하여 발생한 경우 걱정할 필요가 없습니다.
  3. 분기를 사용할 수 있습니다. 이는 관련없는 작업에 영향을주지 않으면 서 장기 / 실험 코드에서 작업하는 좋은 방법입니다.

코드 복사 / 붙여 넣기시주의

내 코드의 스타일은 복잡하고 다른 방법이나 코드 행을 복사하여 대체 할 수있는 오래된 주석으로 채워져 있습니다.

  • 코드 복사 / 붙여 넣기로 시간을 절약 할 수 있지만, 특히 자신이 작성하지 않은 코드 인 경우 (예 : 동료의 코드 인 경우) 가장 위험한 작업 중 하나입니다.

  • 코드가 작동하고 테스트 되 자마자 변수 이름을 바꾸거나 이해할 수없는 것을 주석 처리하기 위해 코드를 신중하게 검토하는 것이 좋습니다.



6

거래 도구는 일반적으로 필요를 해결하기 위해 고안되었습니다. 도구를 사용해야 할 필요가있는 경우 그렇지 않은 경우에는 그럴 필요가 없습니다.

특히 과학 프로그램은 최종 목표가 아니라 수단입니다. 현재 문제를 해결하기 위해 프로그램을 작성합니다. 10 년 동안 다른 사람이 해당 프로그램을 사용 (및 유지 보수해야 함)하지 않을 것입니다. 혼자는하지 않는 것이 의미 현재 개발자는 단위 테스트와 같은 코드의 버전 제어, 또는 캡처 기능과 같은 다른 사람을 위해 역사를 기록 할 수있는 도구 중 하나에 생각.

그러면 어떤 혜택이 있습니까?

  • 버전 관리는 작업을 매우 쉽게 백업 할 수 있기 때문에 좋습니다. 2018 년 현재 github은 매우 인기있는 곳입니다 (필요한 경우 언제든지 나중에 이동할 수 있습니다-git은 매우 유연합니다). 저렴하고 간단한 백업 대체 방법은 운영 체제 (Mac 용 Time Machine, Linux 용 rsync 등)의 자동 백업 절차입니다. 코드는 여러 곳에 있어야합니다!
  • 단위 테스트는 코드를 먼저 작성하면 실제로 코드의 기능을 확인하는 방법에 대해 생각해야하므로 코드에보다 유용한 API를 설계하는 데 도움이 되기 때문에 좋습니다 . 나중에 재사용 할 코드를 작성하고 알고리즘을 변경하는 동안 도움이되는 경우에 유용합니다.
  • 문서. 사용하는 프로그래밍 언어 (예 : Java 용 Javadoc)로 올바른 문서 작성 방법을 배우십시오. 미래를 위해 당신을 쓰십시오. 이 과정에서 변수 이름이 좋으면 문서화가 더 쉬워집니다. 반복합니다. 시인과 시가하는 것과 같은 양의주의를 문서에 제공하십시오.
  • 좋은 도구를 사용하십시오. 당신 을 도와주고 잘 배우는 IDE를 찾으십시오 . 더 좋은 이름으로 변수 이름을 바꾸는 것과 같은 리팩토링은 훨씬 쉽습니다.
  • 동료가있는 경우 동료 검토 사용을 고려하십시오. 외부인이 귀하의 코드를보고 이해하게하는 것은 현재와 미래의 버전입니다. 동료가 코드를 이해하지 못하면 나중에 이해하지 못할 것입니다.

이 답변이 공감대를받지 못한 이유는 무엇입니까? 지금이 있습니다. 우리 그룹은 동료 검토가 가장 효과적인 도구 중 하나라는 것을 발견했습니다. 과학 코드에 관해서는 단위 테스트보다 훨씬 중요합니다. 과학 저널 기사의 복잡한 방정식 세트를 코드로 변환 할 때 오류가 발생하기 쉽습니다. 과학자와 엔지니어는 종종 극도로 가난한 프로그래머를 만듭니다. 동료 검토는 코드를 유지 관리 / 이해 / 사용하기 어려운 구조적 추악함을 포착 할 수 있습니다.
David Hammen

5

이미 좋은 조언 외에도 프로그래밍의 목적과 중요한 점을 고려할 수도 있습니다.

"프로그래밍으로 테스트하거나 연구하는 것은 수학이나 과학에 관한 것입니다."

자신의 이해를 위해 무언가를 실험하고 테스트하는 것이 목적이며 결과가 무엇인지 알아야하는 경우 코드가 기본적으로 빨리 버려지고 현재 접근 방식으로는 충분할 수 있지만 개선 될 수는 있습니다. 결과가 예상과 다른 경우 돌아가서 검토 할 수 있습니다.

그러나 코딩 결과가 연구 방향을 알려주고 결과 무엇인지 모를 경우 정확성이 특히 중요합니다. 코드에 오류가 있으면 전반적인 연구에 다양한 나쁜 영향을 미치므로 실험에서 잘못된 결론을 도출 할 수 있습니다.

이 경우, 단위 테스트를 통해 코드를 이해하기 쉽고 검증 가능한 기능으로 나누면 결과에 대한 자신감이 높아지고 나중에 더 많은 좌절로부터 벗어날 수 있습니다.


5

버전 제어 및 단위 테스트는 전체 코드를 체계적으로 구성하고 기능적으로 유지하기위한 것이지만 실제로 더 깨끗한 코드를 작성하는 데 도움이되지는 않습니다.

  • 버전 관리를 사용하면 코드가 어떻고 지저분 해지는 지 확인할 수 있습니다.
  • 단위 테스트는 코드가 완전히 엉망이더라도 여전히 작동하는지 확인합니다.

당신이 할 때 : 당신이 지저분한 코드를 작성에서 자신을 중지하려면, 당신은 혼잡이 일어날 경우 작동하는 도구가 필요 쓰기 코드를. 널리 사용되는 도구를 린터라고합니다. 나는 파이썬 개발자가 아니지만 Pylint 가 좋은 옵션 인 것처럼 보입니다 .

린 터는 작성한 코드를 살펴보고 구성 가능한 모범 사례와 비교합니다. linter에 변수가라는 규칙이 있고에 변수 camelCase를 작성 snake_case하면 실수로 플래그가 지정됩니다. 좋은 린 터는 "선언 된 변수를 사용해야합니다"에서 "기능의 순환 복잡도는 3보다 작아야합니다"에 이르는 규칙을 가지고 있습니다.

대부분의 코드 편집기는 저장할 때마다 또는 일반적으로 입력 할 때 린터를 실행하고 인라인으로 문제를 표시하도록 구성 할 수 있습니다. 당신이 뭔가를 입력하는 경우 x = 7는은 x(즉, 사용자가 설정 한 무슨 경우) 이상, 더 나은 이름을 사용하는 명령으로, 강조 표시됩니다. 이것은 대부분의 워드 프로세서에서 맞춤법 검사처럼 작동하여 무시하기 어렵고 더 나은 습관을 기르는 데 도움이됩니다.


훨씬 더 많은 투표가 있어야합니다. +1
헤더

2
그러나 천국을 위해 린터를 원하는 스타일로 구성하는 방법을 알고 있어야합니다. 그렇지 않으면 소란으로 화를 낼 수 있습니다.
DrMcCleod

4

나열된 모든 것은 은유 적 인 도구 상자의 도구입니다. 인생의 다른 것들과 마찬가지로 다른 도구는 다른 작업에 적합합니다.

다른 엔지니어링 분야와 비교할 때 소프트웨어는 그 자체로 매우 간단한 개별 조각으로 작동합니다. 과제 성명서는 방의 온도 변동에 따라 다르게 평가되지 않습니다. if문은 제자리에 부식 잠시 후 같은 일을 반환 유지하지 않습니다. 그러나 개별 요소는 매우 단순하고 인간이 작성한 소프트웨어이기 때문에 결과가 너무 커지고 복잡 해져서 사람들이 정신적으로 관리 할 수있는 한계에 도달 할 때까지 이러한 요소는 더 큰 조각으로 결합됩니다.

소프트웨어 프로젝트가 성장하고 성장함에 따라 사람들은 소프트웨어 프로젝트를 연구하고 그 복잡성을 관리하기위한 도구를 만들었습니다. OOP가 한 예입니다. 점점 더 추상적 인 프로그래밍 언어가 또 다른 수단입니다. 소프트웨어의 많은 돈이 더 많은 일을하고 있기 때문에 이를 달성하기위한 도구는 여러분이보고 읽을 것입니다. 그러나 그러한 상황은 당신에게 적용되지 않는 것 같습니다.

따라서 그 중 하나를 수행 해야 한다고 생각하지 마십시오 . 하루가 끝나면 코드는 끝의 수단 일뿐입니다. 불행히도, 무엇이 무엇이고 무엇이 적절하지 않은지에 대한 올바른 관점을 제공하는 것은 도구 상자가 마음에들 때 무엇이 ​​빠졌는지 아는 것이 훨씬 어렵 기 때문에 일부 큰 프로젝트에서 작업하는 것입니다.

어쨌든 스크립트가 작은 한 OOP 또는 다른 기술을 사용하지 않을 것에 대해 걱정하지 않습니다. 당신이 묘사 한 많은 문제는 일반적인 전문적인 조직 기술입니다. 즉, 오래된 파일을 잃지 않는 것은 모든 분야가 다루어야 할 문제입니다.


4

지금까지 제공된 모든 좋은 제안 외에도 시간이 지남에 따라 배운 필수 관행 중 하나는 코드에 자세한 주석을 매우 자유롭게 추가하는 것입니다. 오랜 시간이 지난 후에 무언가로 돌아올 때 가장 중요한 것은 하나입니다. 당신이 생각하는 것을 스스로에게 설명하십시오. 시간이 좀 걸리지 만 비교적 쉽고 통증이 없습니다.

때로는 개념이나 기술이 나에게 익숙하지 않고 자신에게 설명 할 때 코드에 비해 2 ~ 3 배 많은 주석이 있습니다.

버전 관리, 관행 개선 등 .... 위의 모든 사항을 수행하십시오. 그러나 당신이 갈 때 당신에게 일을 설명하십시오. 정말 잘 작동합니다.


4

이런 종류의 프로그램에 어떤 자질이 중요합니까?

유지 관리 나 진화가 쉬운 지 여부는 중요하지 않습니다. 기회가 없을 가능성이 있기 때문입니다.

그것이 얼마나 효율적인지는 중요하지 않을 것입니다.

훌륭한 사용자 인터페이스가 있는지 또는 악의적 인 공격자로부터 안전한지 여부는 중요하지 않습니다.

코드를 읽는 사람이 자신이 주장하는 작업을 쉽게 수행 할 수 있다는 것을 쉽게 읽을 수 있다는 것이 중요합니다.

확실히 맞다는 것이 중요합니다. 프로그램이 부정확 한 결과를 제공하는 경우 이는 과학적 결론입니다. 그러나 실제로 처리하도록 요청하는 입력 만 올바르게 처리하면됩니다. 모든 데이터 값이 양수이면 음의 입력 데이터 값이 주어지면 넘어 지는지 여부는 실제로 중요하지 않습니다.

또한 일정 수준의 변경 제어를 유지 관리해야합니다. 과학적 결과는 재현 할 수 있어야하며, 이는 출판하려는 결과를 산출 한 프로그램의 버전을 알아야합니다. 개발자가 한 명뿐이므로 변경 제어가 매우 정교 할 필요는 없지만 특정 시점으로 돌아가 결과를 재현 할 수 있는지 확인해야합니다.

따라서 프로그래밍 패러다임, 객체 지향, 알고리즘 우아함에 대해 걱정하지 마십시오. 명확성과 가독성 및 시간이 지남에 따른 변경 사항의 추적 가능성에 대해 걱정하지 마십시오. 사용자 인터페이스에 대해 걱정하지 마십시오. 가능한 모든 입력 매개 변수 조합을 테스트하는 것에 대해 걱정하지 말고 결과 및 결론이 유효하다는 것을 확신하고 다른 사람들이 확신 할 수 있도록 충분한 테스트를 수행하십시오.


4

나는 많은 (수학 / 과학) 코드를 작성하는 학자와 비슷한 환경에서 일했지만 설명과 같은 이유로 진행이 느립니다. 그러나 여러 프로젝트에서 사용할 수있는 특수 라이브러리 모음을 작성하고 유지 관리하는 데 도움이 될 수있는 한 가지 특별한 점을 발견했습니다. 이 라이브러리는 유틸리티 기능을 제공해야하므로 현재 프로젝트를 문제 도메인에 맞게 유지하는 데 도움이됩니다.

예를 들어, 필드에서 많은 좌표 변환 (ECEF, NED, 위도 / 경도, WGS84 등)을 처리 convert_ecef_to_ned()해야하는 경우 와 같은 기능은 이라는 새 프로젝트로 이동해야합니다 CoordinateTransformations. 프로젝트를 버전 관리하에두고 부서의 서버에 호스팅하여 다른 사람들이 프로젝트를 사용하고 개선 할 수 있도록합니다. 그런 다음 몇 년이 지나면 프로젝트에 특정 문제 / 연구 도메인과 관련된 코드 만 포함 된 강력한 라이브러리 모음이 있어야합니다.

좀 더 일반적인 조언 :

  • 항상 문제가 무엇이든 관계없이 특정 문제를 가능한 정확하게 모델링하는 것을 목표로합니다. 그렇게하면 변수를 어디에 / 어떻게 / 어떻게 배치할지와 같은 소프트웨어 설계 질문에 대답하는 것이 훨씬 더 분명 해져야합니다.
  • 과학 코드가 아이디어와 개념을 설명하고 더 창의적이고 유동적이기 때문에 테스트 중심 개발을 방해하지 않습니다. 정의 할 API, 유지 관리 서비스, 기능 변경시 다른 사람의 코드에 대한 위험 등이 없습니다.

다른 사람들이 그것을 향상시키지 못하게하십시오. 그들은 코드의 목적을 이해하지 못하고 일을 엉망으로 만들 것입니다.
mathreadler

@mathreadler 글쎄 만약 그들이 일반적인 유틸리티 라이브러리라면 다른 사람들이 엉망으로 만드는 것이 조금 어려울 것입니다.
jigglypuff

범용 라이브러리를 망칠 수없는 이유는 무엇입니까? 당신이 무엇을하고 있는지 전혀 모르거나 그 문제에 대해 정말로 열심히 노력한다면 그렇게 어렵지 않습니다.
mathreadler

@mathreadler 예를 들어 좌표 변환이나 단위 변환을 수행하는 방법은 일반적으로 하나뿐이기 때문입니다.
jigglypuff

일반적으로 숫자가 메모리에 저장되는 방식, 사용하는 표현 및 기타 많은 것들, 라이브러리를 컴파일하려는 CPU에 따라 많은 방법이 있습니다. 한 코더는 모든 사람이 항상 IEEE 배를 사용한다고 가정 할 수 있지만, 다른 코더는 거의 항상 단 정밀도 또는 세 번째 더 이상한 형식을 사용합니다. 한 코더는 템플릿 다형성을 사용하지만 다른 코더는 그것에 다를 수 있습니다. 또 다른 코더는 저수준 c 또는 어셈블리의 모든 것을 하드 코딩하는 데 더 이상한 것입니다.
mathreadler

3

다음은 나의 의견이며 내 자신의 특정 경로에 의해 많은 영향을받습니다.

코딩은 종종 어떻게해야하는지에 대한 독단적 인 관점을 유발합니다. 기술과 도구 대신 적절한 전략을 결정하기 위해 누적 가치와 비용을 검토해야한다고 생각합니다.

읽기 쉽고 디버깅 가능한 코드를 작성하려면 많은 시간과 노력이 필요합니다. 계획 지평이 제한적인 경우가 많기 때문에이를 수행 할 가치가 없습니다 (분석 마비).

한 동료는 경험의 법칙을 가지고있었습니다. 세 번째로 본질적으로 같은 종류의 일을하고 있다면 노력을 투자하십시오. 그렇지 않으면 빠르고 더러운 작업이 적합합니다.

어떤 종류의 테스트는 필수적이지만, 일회성 프로젝트의 경우 단순히 시선이 충분할 수 있습니다. 실질적인 테스트 및 테스트 인프라는 필수적입니다. 값은 코딩 할 때 해방되며 비용은 테스트가 특정 구현에 중점을두면 테스트도 유지 보수가 필요하다는 것입니다. 테스트는 또한 사물이 어떻게 작동해야하는지 상기시켜줍니다.

내 자신의 일회성 스크립트 (종종 확률의 추정 또는 이와 유사한 것의 경우)에 대해 두 가지 작은 것이 매우 유용하다는 것을 알았습니다. 1. 코드 사용 방법을 보여주는 주석을 포함시킵니다. 2. 코드를 작성한 이유에 대한 간단한 설명을 포함하십시오. 코드를 작성할 때 이러한 것들이 굉장히 명백하지만 시간이 지나면 명확성이 낭비됩니다. :-).

OOP는 코드 재사용, 추상화, 캡슐화, 팩토링 등에 관한 것입니다. 매우 유용하지만 품질 코드 및 디자인 생성이 최종 목표가 아닌 경우 쉽게 잃어 버리기 쉽습니다. 양질의 재료를 생산하려면 시간과 노력이 필요합니다.


3

단위 테스트에는 장점이 있다고 생각하지만 과학적 개발에는 의심의 여지가 있습니다. 종종 많은 가치를 제공하기에는 너무 작습니다.

그러나 나는 과학 코드에 대한 통합 테스트를 정말로 좋아합니다.

ETL 파이프 라인과 같이 자체적으로 작동 할 수있는 작은 코드 조각을 분리하십시오. 그런 다음 데이터를 제공하는 테스트를 작성하고 etl 파이프 라인 (또는 단계)을 실행 한 다음 결과가 예상과 일치하는지 테스트하십시오. 테스트 된 청크는 많은 코드가 될 수 있지만 테스트는 여전히 가치를 제공합니다.

  1. 코드를 다시 실행하는 편리한 후크가있어 자주 실행하는 데 도움이됩니다.
  2. 테스트에서 몇 가지 가정을 테스트 할 수 있습니다
  3. somethink가 깨지면 실패한 테스트를 추가하고 수정하기가 쉽습니다.
  4. 입력 데이터 형식을 추측하려고 할 때 발생하는 일반적인 두통을 피하면서 예상되는 입력 / 출력을 체계화합니다.
  5. IT 테스트는 단위 테스트만큼이나 단순하지는 않지만 코드를 분리하고 코드에 경계를 추가하도록 도와줍니다.

이 기술을 자주 사용하고 있으며 비교적 읽기 쉬운 주요 기능으로 끝나는 경우가 많지만 하위 기능은 종종 길고 추악하지만 강력한 I / O 경계로 인해 신속하게 수정 및 재배치 할 수 있습니다.


2

나는 일반적으로 매우 큰 소스 기반에서 작업합니다. 우리는 당신이 언급 한 모든 도구를 사용합니다. 최근에, 사이드 프로젝트를 위해 일부 파이썬 스크립트 작업을 시작했습니다. 그들은 최대 수십에서 수백 줄입니다. 습관적으로 나는 스크립트를 소스 제어에 맡겼다. 작동하지 않을 수도있는 실험을 시도하기 위해 분기를 만들 수 있기 때문에 유용했습니다. 코드를 복제하고 다른 목적으로 수정해야하는 경우 포크 할 수 있습니다. 다시 가져와야 할 경우를 대비하여 원본을 그대로 둡니다.

"단위 테스트"의 경우, 수동으로 확인하는 알려진 출력을 생성하기위한 입력 파일이 있습니다. 아마도 자동화 할 수는 있지만 그렇게하면 절약하는 것보다 시간이 더 걸릴 것 같습니다. 스크립트를 얼마나 자주 수정하고 실행해야하는지에 따라 다릅니다. 어느 쪽이든, 작동한다면 해보십시오. 그것이 가치보다 더 문제가 있다면, 시간을 낭비하지 마십시오.


2

일반적인 코드 작성과 마찬가지로 코드 작성시 주요 질문은 다음과 같습니다.

어떤 독자를 염두에두고 있습니까? 또는 누가 코드를 소비합니까?

공식적인 코딩 지침과 같은 것은 당신이 유일한 독자 일 때는 의미가 없습니다.

반면에, 코드를 작성하는 것이 도움이 될 것입니다. 미래의 미래를 이해할 수 있습니다.

"좋은 스타일"이 가장 도움이되는 스타일입니다. 그 스타일은 내가 줄 수없는 대답입니다.

150 LOC 파일에 대해서는 OOP 또는 단위 테스트가 필요하지 않다고 생각합니다. 진화하는 코드가있을 때 전용 VCS가 흥미로울 것입니다. 그렇지 않으면 .bak트릭을 수행합니다. 이 도구는 질병 제거를위한 치료법입니다.

아마도 취한 상태에서 코드를 읽었더라도 읽고 이해하고 수정할 수있는 방식으로 코드를 작성해야합니다.

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