함수에 전체 bash 스크립트를 작성하는 이유는 무엇입니까?


59

직장에서 bash 스크립트를 자주 작성합니다. 관리자가 다음 예제와 같이 전체 스크립트를 기능으로 나눌 것을 제안했습니다.

#!/bin/bash

# Configure variables
declare_variables() {
    noun=geese
    count=three
}

# Announce something
i_am_foo() {
    echo "I am foo"
    sleep 0.5
    echo "hear me roar!"
}

# Tell a joke
walk_into_bar() {
    echo "So these ${count} ${noun} walk into a bar..."
}

# Emulate a pendulum clock for a bit
do_baz() {
    for i in {1..6}; do
        expr $i % 2 >/dev/null && echo "tick" || echo "tock"
        sleep 1
    done
}

# Establish run order
main() {
    declare_variables
    i_am_foo
    walk_into_bar
    do_baz
}

main

"가독성"이외의 다른 이유가 있습니까? 몇 가지 의견과 줄 간격으로 동일하게 설정할 수 있을까요?

스크립트를보다 효율적으로 실행합니까 (실제로 반대의 경우가 예상됩니다) 또는 앞에서 언급 한 가독성을 넘어서 코드를 수정하는 것이 더 쉬워 집니까? 아니면 정말 문체 선호입니까?

스크립트가 잘 보여주지 않지만, 우리의 실제 스크립트 함수의 "실행 순서가"매우 선형 경향이 있습니다은 - walk_into_bar물건에 따라 i_am_foo수행하고 있으며, do_baz가 설정 한 물건에 작용 walk_into_bar- 그래서 인 실행 순서를 임의로 바꿀 수있는 것은 일반적으로 우리가하는 일이 아닙니다. 예를 들어, 갑자기 declare_variables뒤에 넣기를 원하지 않을 경우 문제가 발생 walk_into_bar합니다.

위의 스크립트를 작성하는 방법의 예는 다음과 같습니다.

#!/bin/bash

# Configure variables
noun=geese
count=three

# Announce something
echo "I am foo"
sleep 0.5
echo "hear me roar!"

# Tell a joke
echo "So these ${count} ${noun} walk into a bar..."

# Emulate a pendulum clock for a bit
for i in {1..6}; do
    expr $i % 2 >/dev/null && echo "tick" || echo "tock"
    sleep 1
done

30
나는 당신의 상사를 좋아합니다. 내 스크립트에서 나는 main()상단 main "$@"에 놓고 하단에 추가 하여 호출합니다. 이를 통해 높은 수준의 스크립트 로직을 열 때 가장 먼저 볼 수 있습니다.
존 Kugelman

22
나는 가독성이 "몇 개의 주석과 줄 간격으로 동일하게 설정 될 수있다"는 생각에 동의하지 않는다. 허구를 제외하고는, 각 장과 섹션에 대한 목차와 설명이없는 책을 다루고 싶지 않습니다. 프로그래밍 언어에서, 그것은 함수가 제공 할 수있는 가독성이며, 주석은 그렇지 않습니다.
Rhymoid

6
함수에 선언 된 변수는 선언해야합니다. 이는 사소한 스크립트에서 매우 중요한 local변수 범위 를 제공합니다 .
거미 보리스

8
나는 당신의 상사와 동의하지 않습니다. 스크립트를 함수로 세분화해야한다면, 우선 쉘 스크립트를 작성해서는 안됩니다. 대신 프로그램을 작성하십시오.
el.pescado

6
함수는 스크립트 내에서 또는 둘 이상의 스크립트에서 반복되는 프로세스를위한 것입니다. 또한 균일 한 방법론을 적용 할 수 있습니다. 예를 들어 syslog에 쓰는 함수를 사용합니다. 모든 사람이 동일한 기능을 사용하는 한 syslog 항목이 더 일관성이 있습니다. 예제와 같은 일회용 함수는 스크립트를 불필요하게 복잡하게 만듭니다. 경우에 따라 문제가 발생합니다 (변수 범위 지정).
Xalorous

답변:


39

Kfir Lavi의 블로그 게시물 "Defensive Bash Programming" 을 읽은 후 이와 동일한 스타일의 bash 프로그래밍을 사용하기 시작했습니다 . 그는 몇 가지 좋은 이유를 제시하지만 개인적으로 나는 이것이 가장 중요하다고 생각합니다.

  • 프로시 저는 설명이됩니다. 코드의 특정 부분이 무엇을해야하는지 파악하는 것이 훨씬 쉽습니다. 코드 월 대신 "아, find_log_errors함수가 로그 파일에서 오류를 읽습니다"라는 메시지가 표시됩니다. 신을 사용하는 awk / grep / sed 라인을 찾는 것과 긴 스크립트 중간에 어떤 유형의 정규 표현식을 알고 있는지 비교하십시오.

  • set -x및 로 묶어서 함수를 디버깅 할 수 있습니다 set +x. 나머지 코드가 제대로 작동한다는 것을 알고 나면이 트릭을 사용하여 특정 기능 만 디버깅하는 데 집중할 수 있습니다. 물론 스크립트의 일부를 묶을 수 있지만 긴 부분이라면 어떻게해야합니까? 다음과 같이하는 것이 더 쉽습니다.

     set -x
     parse_process_list
     set +x
    
  • 로 인쇄 사용량 cat <<- EOF . . . EOF. 코드를 훨씬 전문적으로 만들기 위해 꽤 많이 사용했습니다. 또한, parse_args()함께 getopts기능이 매우 편리합니다. 다시 말하지만, 텍스트의 거대한 벽으로 스크립트에 모든 것을 넣는 대신 가독성에 도움이됩니다. 이것들을 재사용하는 것이 편리합니다.

그리고 분명히 이것은 C 또는 Java 또는 Vala를 알고 있지만 bash 경험이 제한된 사람에게는 훨씬 더 읽기 쉽습니다. 효율성에 관해서는 할 수있는 일이 많지 않습니다 .bash 자체가 가장 효율적인 언어는 아니며 사람들은 속도와 효율성에 관해서 perl과 python을 선호합니다. 그러나 다음과 nice같은 기능을 수행 할 수 있습니다 .

nice -10 resource_hungry_function

각 코드 줄마다 nice를 호출하는 것과 비교하여 타이핑이 줄고 스크립트의 일부만 낮은 우선 순위로 실행하려는 경우 편리하게 사용할 수 있습니다.

제 생각에 백그라운드에서 함수를 실행하면 백그라운드에서 실행되는 명령문을 많이 원할 때 도움이됩니다.

이 스타일을 사용한 예제 중 일부 :


3
나는 당신이 그 기사의 제안을 매우 진지하게 받아 들여야한다는 것을 확신하지 못한다. 물론 몇 가지 좋은 아이디어가 있지만 스크립팅에 익숙한 사람은 아닙니다. 예제에서 단일 변수는 인용 되지 않습니다 ! (!) 그리고 기존 환경 변수와 충돌 할 수 있기 때문에 매우 나쁜 아이디어 인 UPPER CASE 변수 이름을 사용하는 것이 좋습니다. 이 답변 요점은 의미가 있지만 링크 된 기사는 다른 언어에 익숙하고 스타일을 강타로 강요하려는 사람이 작성한 것 같습니다.
terdon

1
@ terdon 나는 기사로 돌아가서 다시 읽었습니다. 저자가 대문자 변수 이름을 언급하는 유일한 장소는 "Immutable Global Variables"입니다. 전역 변수를 함수 환경 내에 있어야하는 변수로 생각하면이를 자본으로 만드는 것이 합리적입니다. 참고로 bash 매뉴얼은 가변 경우에 대한 규칙을 명시하지 않습니다. 여기에서 받아 들여진 대답 조차 "보통"이라고 말하고 유일한 "표준"은 전체 IT 산업을 대표하지 않는 Google의 것입니다.
Sergiy Kolodyazhnyy

다른 메모에서 @terdon, 나는 기사에서 가변 인용이 언급되어야한다는 블로그에 100 % 동의하고 블로그의 의견에서도 지적되었습니다. 또한 다른 언어에 익숙한 지 여부에 관계 없이이 스타일의 코딩을 사용하는 사람을 판단하지 않습니다. 이 모든 질문과 답변은 그에 대한 장점이 있음을 분명히 나타내며, 다른 언어에 익숙한 사람의 정도는 아마도 여기와 관련이 없습니다.
Sergiy Kolodyazhnyy

1
@terdon 글은 기사가 "소스"자료의 일부로 게시되었습니다. 나는 모든 것을 내 의견으로 올릴 수 있었지만 기사에서 배운 것들 중 일부는 시간이 지남에 따라 연구에서 나온 것임을 인정해야했습니다. 저자의 링크 인 페이지는 일반적으로 Linux 및 IT에 대한 경험이 풍부하다는 것을 보여 주므로 기사에서 실제로 그것을 보여주지는 않지만 추측은 Linux 및 쉘 스크립팅과 관련하여 귀하의 경험을 신뢰하므로 귀하가 옳을 수도 있습니다 .
Sergiy Kolodyazhnyy

1
그것은 훌륭한 답변이지만 Bash에 변수 범위를 추가하고 싶습니다. 이런 이유로 함수를 local통해 모든 것을 사용 하고 호출하는 함수 내에서 변수를 선언하는 것을 선호 main()합니다. 이렇게하면 일을 훨씬 더 관리하기 쉽고 혼란스러운 상황을 피할 수 있습니다.
Housni

65

가독성 은 한 가지입니다. 그러나 이것보다 모듈화에 더 많은 것이 있습니다 . ( 반 모듈화 는 기능에 더 적합 할 수 있습니다.)

함수에서 일부 변수를 로컬로 유지할 수 있으므로 안정성 이 높아지고 엉망이 될 가능성이 줄어 듭니다.

기능의 또 다른 장점은 재사용 성 입니다. 함수가 코딩되면 스크립트에서 여러 번 적용될 수 있습니다. 다른 스크립트로 이식 할 수도 있습니다.

코드는 이제 선형 일 수 있지만 나중에 Bash 세계에서 멀티 스레딩 또는 멀티 프로세싱 영역을 입력 할 수 있습니다. 일단 기능에서 일을하는 법을 배우면 병렬로의 발판을 마련 할 수 있습니다.

추가 할 점이 하나 더 있습니다. Etsitpab Nioliv가 아래 주석에서 알 수 있듯이 일관된 엔티티로서의 기능에서 쉽게 리디렉션 할 수 있습니다. 그러나 함수 재 지정의 또 다른 측면이 있습니다. 즉, 기능 정의에 따라 리디렉션을 설정할 수 있습니다. 예 :

f () { echo something; } > log

이제 함수 호출에 명시적인 리디렉션이 필요하지 않습니다.

$ f

이것은 많은 반복을 피할 수 있으며, 이는 다시 신뢰성을 높이고 일을 정돈하는 데 도움이됩니다.

또한보십시오


55
함수로 나뉘면 훨씬 나아지지만 아주 좋은 대답입니다.
Pierre Arlaud

1
어쩌면 기능을 사용하여 (다른 스크립트에 해당 스크립트를 가져올 수 있음을 추가 source하거나 . scriptname.sh, 그들이 당신의 새로운 스크립트에 있던 그대로의 경우 이러한 기능을 사용한다.
SnakeDoc

그것은 이미 다른 답변에서 다룹니다.
Tomasz

1
알겠습니다. 그러나 나는 다른 사람들도 중요하게 생각하고 싶습니다.
Tomasz

7
나는 오늘 스크립트 출력 중 일부를 에코 대신 파일로 (전자 메일을 통해 보내려면) 리디렉션 해야하는 경우에 직면했습니다. 원하는 함수의 출력을 리디렉션하기 위해 간단히 myFunction >> myFile을 수행해야했습니다. 꽤 편리합니다. 관련이있을 수 있습니다.
Etsitpab Nioliv

39

내 의견으로는 함수의 세 가지 장점을 언급했습니다.

  1. 정확성을 테스트하고 확인하기가 더 쉽습니다.

  2. 향후 스크립트에서 함수를 쉽게 재사용 (소스 화) 할 수 있습니다

  3. 당신의 상사는 그들을 좋아합니다.

그리고 3 번의 중요성을 과소 평가하지 마십시오.

하나 이상의 문제를 해결하고 싶습니다.

... 따라서 런 순서를 임의로 바꿀 수있는 것은 일반적으로하는 일이 아닙니다. 예를 들어, 갑자기 declare_variables뒤에 넣기를 원하지 않을 경우 문제가 발생 walk_into_bar합니다.

코드를 함수로 나누는 이점을 얻으려면 함수를 최대한 독립적으로 만들어야합니다. walk_into_bar다른 곳에서 사용되지 않는 변수가 필요한 경우 해당 변수를로 정의하고로 설정해야합니다 walk_into_bar. 코드를 함수로 분리하고 상호 종속성을 최소화하는 프로세스는 코드를 더 명확하고 간단하게 만들어야합니다.

이상적으로는 기능을 개별적으로 쉽게 테스트 할 수 있어야합니다. 상호 작용으로 인해 테스트하기 쉽지 않은 경우 리팩토링을 통해 이점을 얻을 수 있다는 신호입니다.


나는 때때로 의존성을 모델링하고 강제하는 것이 현명하다고 생각하고, 피할 수있는 리팩토링 (충분히 충분하고 털이 많기 때문에 더 이상 모듈화되지 않은 경우로 이어질 수 있음) 기능). 매우 복잡한 유스 케이스는 한 번 프레임 워크 영감을주었습니다 .
Charles Duffy

4
함수로 나눌 필요가 있지만, 예제가 너무 멀다. 나는 정말로 나를 괴롭히는 유일한 것은 변수 선언 함수라고 생각한다. 전역 변수, 특히 정적 변수는 해당 목적을 위해 주석 처리 된 섹션에서 전역 적으로 정의해야합니다. 동적 변수는 사용하고 수정하는 함수에 대해 로컬이어야합니다.
Xalorous

@Xalorous 외부 파일에서 값을 읽는 프로 시저를 개발하기 전에 중간 변수 와 빠른 단계로 전역 변수가 프로 시저에서 초기화 되는 관행을 보았습니다 ... 초기화하지만 이점 3을 얻기 위해 구부려 야하는 경우는 거의 없습니다.;-)
Hastur

13

C / C ++, python, perl, ruby ​​또는 다른 프로그래밍 언어 코드와 같은 이유로 코드를 함수로 나눕니다. 더 깊은 이유는 추상화입니다. 하위 수준의 작업을 상위 수준의 기본 기능 (기능)으로 캡슐화하여 작업 수행 방식에 대해 신경 쓸 필요가 없습니다. 동시에, 코드는 더 읽기 쉽고 유지 보수가 쉬워지고 프로그램 로직이 더 명확 해집니다.

그러나 코드를 살펴보면 변수를 선언하는 함수가 매우 이상합니다. 이것은 정말 눈썹을 상승시킵니다.


과소 평가 된 답변 IMHO. 그렇다면 main함수 / 메소드 에서 변수를 선언 할 것을 제안 합니까?
David Tabernero M.

12

나는 완전히 동의하지만 재사용 성 , 가독성 , 그리고 섬세 상사 키스하지만 함수의 다른 하나 개의 이점이있다 : 변수 범위는 . LDP가 보여주는 것처럼 :

#!/bin/bash
# ex62.sh: Global and local variables inside a function.

func ()
{
  local loc_var=23       # Declared as local variable.
  echo                   # Uses the 'local' builtin.
  echo "\"loc_var\" in function = $loc_var"
  global_var=999         # Not declared as local.
                         # Therefore, defaults to global. 
  echo "\"global_var\" in function = $global_var"
}  

func

# Now, to see if local variable "loc_var" exists outside the function.

echo
echo "\"loc_var\" outside function = $loc_var"
                                      # $loc_var outside function = 
                                      # No, $loc_var not visible globally.
echo "\"global_var\" outside function = $global_var"
                                      # $global_var outside function = 999
                                      # $global_var is visible globally.
echo                      

exit 0
#  In contrast to C, a Bash variable declared inside a function
#+ is local ONLY if declared as such.

실제 쉘 스크립트에서는 이것을 자주 볼 수 없지만 복잡한 스크립트에는 좋은 생각 인 것 같습니다. 응집력 을 줄이면 코드의 다른 부분에서 예상되는 변수를 방해하는 버그를 피할 수 있습니다.

재사용 성은 종종 공통 함수 라이브러리를 작성하고 source해당 라이브러리를 모든 스크립트에 작성하는 것을 의미 합니다. 이렇게하면 더 빨리 달릴 수는 없지만 더 빨리 쓸 수 있습니다.


을 명시 적으로 사용하는 사람은 거의 local없지만 기능으로 분류 된 스크립트를 작성하는 대부분의 사람들은 여전히 ​​디자인 원칙을 따릅니다. Usign local은 버그를 도입하기 어렵게 만듭니다.
Voo

local함수와 그 자식에 변수를 사용할 수 있으므로 함수 A에서 전달할 수 있지만 함수 B에 사용할 수없는 변수를 갖는 것이 좋습니다. 이름이 같지만 다른 목적을 가진 변수를 원할 수도 있습니다. 따라서 범위를 정의하는 데 유용하며 Voo가 말했듯이 버그가 적음
Sergiy Kolodyazhnyy

10

다른 답변에 이미 제공된 것과 완전히 다른 이유 :이 기술이 때때로 사용되는 한 가지 이유는 최상위 수준의 비 기능 정의 문이 호출되는 main경우 스크립트가 실수로 불쾌한 일을하지 않도록하는 것입니다 스크립트가 잘린 경우 스크립트가 프로세스 A에서 프로세스 B (쉘)로 파이프되면 스크립트가 잘릴 수 있으며 프로세스 A는 스크립트 작성이 완료되기 전에 어떤 이유로 든 종료됩니다. 프로세스 A가 원격 리소스에서 스크립트를 가져 오는 경우에 특히 그렇습니다. 좋은 생각이 아닌 보안상의 이유로 수행되는 작업이며 일부 스크립트는 문제를 예상하도록 수정되었습니다.


5
흥미 롭습니다! 그러나 나는 각 프로그램에서 그 일들을 처리해야한다는 것이 문제가된다는 것을 알았습니다. 다른 한편으로,이 main()패턴은 if __name__ == '__main__': main()파일 끝에서 사용하는 파이썬에서 일반적입니다 .
Martin Ueding

1
파이썬 관용구는 다른 import스크립트를 실행하지 않고 현재 스크립트 로 만들 수 있다는 이점이 main있습니다. 비슷한 가드를 bash 스크립트에 넣을 수 있다고 가정합니다.
Jake Cobb

@Jake Cobb 예. 나는 이제 모든 새로운 bash 스크립트에서 그렇게합니다. 모든 새 스크립트에서 사용하는 핵심 기능 인프라가 포함 된 스크립트가 있습니다. 해당 스크립트를 소싱하거나 실행할 수 있습니다. 소스 인 경우 기본 기능이 실행되지 않습니다. 소스 대 실행의 감지는 BASH_SOURCE가 실행 스크립트의 이름을 포함한다는 사실을 통해 이루어집니다. 핵심 스크립트와 동일하면 스크립트가 실행되고있는 것입니다. 그렇지 않으면 소스입니다.
DocSalvager

7

프로세스에는 시퀀스가 ​​필요합니다. 대부분의 작업은 순차적입니다. 주문을 망쳐 놓는 것은 의미가 없습니다.

그러나 스크립팅을 포함한 프로그래밍에 관한 가장 큰 것은 테스트입니다. 테스트, 테스트, 테스트. 스크립트의 정확성을 검증하기 위해 현재 어떤 테스트 스크립트가 필요합니까?

상사는 스크립트 키디에서 프로그래머가되도록 안내합니다. 이것은 좋은 방향입니다. 당신을 따르는 사람들은 당신을 좋아할 것입니다.

그러나. 항상 프로세스 지향 루트를 기억하십시오. 기능이 일반적으로 실행되는 순서대로 정렬되는 것이 합리적이라면 적어도 첫 번째 통과로 수행하십시오.

나중에 함수 중 일부가 입력을 처리하고, 다른 출력, 다른 처리, 기타 모델링 데이터 및 기타 데이터를 조작하는 것을 보게되므로 유사한 방법을 그룹화하는 것이 현명 할 수도 있습니다. .

나중에도 많은 스크립트에서 사용하는 작은 도우미 함수의 라이브러리를 작성했음을 알게 될 것입니다.


6

주석과 간격은 내가 시연하는 것처럼 기능이 읽을 수있는 가독성 근처에 도달 할 수 없습니다 . 기능이 없으면 나무의 숲을 볼 수 없습니다. 큰 문제는 많은 세부 사항 사이에 숨겨져 있습니다. 다시 말해, 사람들은 세세한 부분과 큰 그림에 동시에 집중할 수 없습니다. 짧은 스크립트에서는 분명하지 않을 수 있습니다. 짧게 유지되는 한 충분히 읽을 수 있습니다. 소프트웨어는 더 커지지 만 더 작아지지는 않으며 확실히 회사의 전체 소프트웨어 시스템의 일부입니다. 아마도 수백만 줄에 달할 것입니다.

다음과 같은 지침을 제공했는지 고려하십시오.

Place your hands on your desk.
Tense your arm muscles.
Extend your knee and hip joints.
Relax your arms.
Move your arms backwards.
Move your left leg backwards.
Move your right leg backwards.
(continue for 10,000 more lines)

중간 정도 또는 5 %가 지나면 처음 몇 단계를 잊었을 것입니다. 나무의 숲을 볼 수 없기 때문에 대부분의 문제를 발견 할 수 없었습니다. 기능과 비교 :

stand_up();
walk_to(break_room);
pour(coffee);
walk_to(office);

라인 별 순차 버전에 주석을 몇 개나 넣었는지에 관계없이 훨씬 이해하기 쉽습니다. 또한 커피 를 만드는 것을 잊어 버렸을 가능성이 훨씬 높으며 마지막에는 sit_down ()을 잊었을 것입니다. 당신의 마음이 grep과 awk 정규식의 세부 사항을 생각할 때, 당신은 큰 그림을 생각할 수 없습니다- "커피가 없다면 어떻게해야합니까?"

기능은 주로 큰 그림을보고 커피를 만드는 것을 잊었다는 것을 알 수 있습니다 (또는 누군가가 차를 좋아할 수도 있음). 다른 시점에서 다른 마음가짐으로 자세한 구현에 대해 걱정할 수 있습니다.

물론 다른 답변에서 논의 된 다른 이점도 있습니다. 다른 답변에서 명확하게 언급되지 않은 또 다른 이점은 함수가 버그를 예방하고 수정하는 데 중요한 보증을 제공한다는 것입니다. 적절한 함수 walk_to ()에서 $ foo 변수가 잘못되었다는 것을 발견하면 해당 문제의 다른 6 줄만보고 해당 문제의 영향을받을 수있는 모든 것을 찾아야한다는 것을 알고 있습니다. 잘못되었습니다. (적절한) 기능이 없으면 전체 시스템의 모든 항목과 모든 항목이 $ foo가 올바르지 않은 원인 일 수 있으며 모든 항목과 모든 항목이 $ foo의 영향을받을 수 있습니다. 따라서 프로그램의 모든 한 줄을 다시 검사하지 않으면 $ foo를 안전하게 수정할 수 없습니다. $ foo가 함수의 로컬 인 경우


1
이것은 bash구문 이 아닙니다 . 그것은 수치심이다. 나는 그런 함수에 입력을 전달하는 방법이 없다고 생각합니다. (예 : pour();< coffee). 더 비슷 c++하거나 php(내 생각에) 보인다 .
목소리

2
괄호없이 @ tjt263, bash 구문 : pour coffee. Parens를 사용하면 거의 모든 다른 언어입니다. :)
Ray Morris

5

프로그래밍에 관한 몇 가지 관련 트루 즘 :

  • 상사가 주장하지 않아도 프로그램이 변경됩니다 .
  • 코드와 입력 만 프로그램 동작에 영향을줍니다.
  • 명명 이 어렵다.

의견은 코드 *로 아이디어를 명확하게 표현할 수없는 스톱 갭으로 시작하며, 변화에 따라 악화 (또는 단순히 잘못)됩니다. 따라서 가능하다면 개념, 구조, 추론, 의미론, 흐름, 오류 처리 및 코드 를 코드로 이해하는 것과 관련된 모든 것을 표현하십시오 .

Bash 함수에는 대부분의 언어에서 볼 수없는 몇 가지 문제가 있습니다.

  • Bash에서 네임 스페이스는 끔찍합니다. 예를 들어 local키워드 를 사용하지 않으면 전역 네임 스페이스가 오염됩니다.
  • 를 사용 local foo="$(bar)"하면 의 종료 코드가 손실bar 됩니다.
  • 명명 된 매개 변수가 없으므로 "$@"서로 다른 상황에서 어떤 의미가 있는지 명심해야 합니다.

* 이것이 기분 나빠서 유감이지만, 몇 년간 코멘트를 사용하고 몇 년 동안 코멘트없이 개발 한 후에 ** 우수하다는 것이 분명합니다.

** 라이센스, API 문서 등에 주석을 사용하는 것이 여전히 필요합니다.


나는 ... 함수의 시작 부분에 null로 선언함으로써 거의 모든 지역 변수를 설정 한 local foo=""다음 ... 결과에 따라 행동하는 명령 실행을 사용하여 설정 foo="$(bar)" || { echo "bar() failed"; return 1; }. 이것은 필요한 값을 설정할 수 없을 때 함수에서 빠르게 빠져 나옵니다. 중괄호는 return 1실패시에만 실행 되도록 보장하는 데 필요합니다 .
DocSalvager

5

시간은 돈이다

있다 다른 좋은 답변 작성하기 위해 기술적 인 이유에 빛을 확산 모듈 식으로 사용할 수 있도록 개발 된 작업 환경에서 개발 된 잠재적으로 긴 스크립트를,,, 사람의 그룹 과 자신의 사용뿐만.

나는 작업 환경에서 "시간은 돈이다"라는 기대 에 초점맞추고 싶다 . 따라서 버그가없고 코드 성능이 가독성 , 테스트 가능성, 유지 관리 가능성, 리팩토링 가능성 , 재사용 가능성 과 함께 평가됩니다 ...

"모듈" 로 코드를 작성 하면 코더 자체뿐만 아니라 테스터 또는 보스가 사용하는 시간까지 필요한 읽기 시간이 줄어 듭니다 . 또한 상사의 시간은 일반적으로 코더의 시간보다 더 많이 지불되며 상사는 업무의 질을 평가할 것입니다.

또한 독립적 인 "모듈" 로 코드 (bash 스크립트도 포함)를 작성하면 팀의 다른 구성 요소와 "병렬" 로 작업 하여 전체 생산 시간을 단축하고 단일 전문 지식을 최대한 활용하여 부품을 검토하거나 재 작성할 수 있습니다. " 있는 그대로 " 작성한 코드를 재활용하기 위해 다른 것에 대한 부작용이 없습니다.다른 프로그램 / 스크립트의 경우 라이브러리 (또는 스 니펫 라이브러리)를 작성하고 전체 크기와 관련 오류 가능성을 줄이고 각 부분을 철저히 디버그하고 테스트합니다 ... 물론 논리 섹션에서 프로그램을 구성합니다 / script 및 가독성을 향상시킵니다. 시간과 돈을 절약 할 수있는 모든 것. 단점은 표준을 고수하고 기능에 주석을 달아야한다는 것입니다 (그렇지만 작업 환경에서해야 할 일).

표준 을 준수 하면 처음에는 작업 속도가 느려지지만 나중에 다른 모든 작업의 ​​속도가 빨라집니다. 실제로 협업에 관련된 사람들의 수가 증가하면 피할 수없는 요구가됩니다. 예를 들어 전역 변수가 함수가 아닌 전역 적으로 정의되어야한다고 생각하더라도 declare_variables()첫 번째 줄에서 항상 호출 되는 함수에서 변수를 초기화하는 표준을 이해할 수 있습니다 main()...

마지막으로, 현대 소스 코드 편집기에서 선택적으로 분리 된 루틴을 표시하거나 숨길 가능성을 과소 평가하지 마십시오 ( 코드 접기 ). 이렇게하면 코드가 간결 해지고 사용자가 다시 시간을 절약 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

위 의 기능 만 어떻게 전개 되는지 볼 수 있습니다 walk_into_bar(). 다른 것조차도 각각 1000 줄 길이 였지만 여전히 단일 페이지에서 모든 코드를 제어 할 수 있습니다. 변수를 선언 / 초기화하는 섹션에도 접혀 있습니다.


1

다른 답변에서 주어진 이유를 제외하고 :

  1. 심리학 : 생산성이 코드 라인으로 측정되는 프로그래머는 불필요하게 자세한 코드를 작성하는 데 도움이됩니다. 더 많은 관리가 코드 라인에 집중할수록 프로그래머는 불필요하게 복잡한 코드를 확장해야합니다. 복잡성이 증가하면 유지 관리 비용이 증가하고 버그 수정에 필요한 노력이 증가 할 수 있으므로 바람직하지 않습니다.

다운 보트가 말하는 것처럼 그렇게 나쁜 대답은 아닙니다. 참고 : agc는 또한 이것이 가능성이라고 말합니다. 그렇습니다. 그는 그것이 유일한 가능성이라고 말하지 않으며, 누군가를 비난하지 않고, 사실만을 진술합니다. 비록 오늘날 "직접"코드 라인 "->"$$ "스타일의 계약 작업은 거의 들어 본 적이 없지만, 간접적으로는 생성 된 코드의 양이 리더 / 보스에 의해 계산된다는 것은 매우 일반적입니다.
user259412

0

종종 간과되는 또 다른 이유는 bash의 구문 분석입니다.

set -eu

echo "this shouldn't run"
{
echo "this shouldn't run either"

이 스크립트에는 분명히 구문 오류가 있으며 bash는 전혀 실행하지 않아야합니다. 잘못된.

~ $ bash t1.sh
this shouldn't run
t1.sh: line 7: syntax error: unexpected end of file

함수에 코드를 래핑하면 이런 일이 발생하지 않습니다.

set -eu

main() {
  echo "this shouldn't run"
  {
  echo "this shouldn't run either"
}

main
~ $ bash t1.sh
t1.sh: line 10: syntax error: unexpected end of file
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.