"아직 수행하지 않은 경우 수행"에 대한 용어 (또는 "패턴"?) [닫힘]


54

꽤 기본적으로 들리지만, 최근에 동료에게 호출 된 메소드 startHttpServer가 서버가 아직 실행 중이 지 않은 경우에만 서버를 시작하기 때문에 이해하기에는 너무 복잡하다고 말합니다. "정말입니까? 수십 년 동안이 일을 해왔습니다. 프로그래밍에서 일반적인 패턴입니다."라고 대답하면 문제가 생깁니다. 내가 인정하는 것보다 더 자주 그는 전체 프로그래밍 공동체가 그의 견해 뒤에 있다는 것을 보여주는 문서화 된 증거를 가지고 돌아 왔고 결국 나는 양 같은 느낌이 든다.

질문 : 필요한 조치가 이미 적용되고있는 경우 비 작동 인 방법의 개념 뒤에 문서화 된 설계 패턴이 있습니까? 또는 패턴이 아닌 경우 이름도 있습니까? 그렇지 않다면, 이런 방식으로 방법을 작성하는 것을 고려하기가 너무 복잡하다고 생각할만한 이유가 있습니까?


6
캐싱 처럼 들리며 종종 실제로 복잡한 것으로 간주됩니다 ( $ {something}에서 $ {someone}까지 어떻게 설명합니까? 참조 )
— gnat

8
세 가지 답변이 있지만 가장 좋은 대답은 모두 적용하는 것입니다. 원래 함수의 이름을 바꾸고 코드를 두 개의 함수로 나누고 (두 가지 중 하나가 이제 이름을 startHttpServer얻음) "예"라는 용어가 여기에 적용됩니다. 잘.
— Doc Brown

8
동료는 어떤 종류의 반 증거를 제공합니까? 당신은 그것에 링크를 제공 할 수 있습니까?
— Robert Harvey

5
동료가 인용문을 어디에서 구했는지 궁금합니다. 적어도 스택 오버플로 및 소프트웨어 엔지니어링과 관련하여이 함수는 이름이 잘못 지정되었지만 비정상적인 동작은 없습니다. 누군가가 블로그에 프로그래밍 커뮤니티의 전체 견해를 나타내는 무언가를 블로그에 넣었 기 때문이 아닙니다. Martin Fowler와 같은 큰 이름조차도 때때로 매우 이상한 것을 말합니다. 우리는 모두 인간 일뿐입니다.
— T. Sar-복원 모니카

4
"아직 수행하지 않은 경우 수행"에 대해 생각하는 더 좋은 방법은 "시스템을이 상태에 두십시오"라고 생각합니다. 물론, 시스템이 이미 그 상태에 있다면, 방법은 아무것도하지 않을 것입니다 – 이것은 예상되는 행동입니다.
— T. Sar-복직 모니카

답변:


127

NickWilliams과 같이 말했다 이미있다 : 영업 설명하는 개념이라고 나무 등 (명사 멱등을 ). 실제로는 특히 고급 API에서 일반적입니다.

그러나 기능의 이름을 바꿉니다.

또는 로 startHttpServer전화하십시오 .makeSureHttpServerIsRunningensureHttpServerIsRunning

함수가 호출 startHttpServer되면 독자는 HTTP 서버를 시작할 것으로 예상합니다. 10 번 연속 호출하면 10 대의 서버가 실행됩니다. 함수는 대부분 그렇게하지 않습니다. 또한 "start"라는 이름은 하나의 서버 만 실행하려면 함수가 이미 호출되었는지 여부를 추적해야 함을 나타냅니다.

함수가 호출 makeSureHttpServerIsRunning되면 HTTP 서버가 이미 실행 중인지 확인하고 필요한 경우 시작하여 HTTP 서버가 실행 중인지 확인하는 데 필요한 작업을 수행한다고 가정합니다. 또한 함수가 서버가 실제로 실행되고 있는지 확인한다고 가정합니다 (서버를 시작하면 아직 실행되지 않는 시간이 걸릴 수 있음).


83
이. 개인적으로 나는 "확인"을 대신 사용합니다. 요점은 이것이 팀에서 이해하는 명명 체계가되어야한다는 것입니다.
— Euphoric

3
이미 시작된 경우 예외를 시작했습니다. sqlconnection.open 같은
— Ewan

9
나는 항상 "이미 그렇지 않은 경우"기능에 대해 "확인"이름을 사용합니다.
— Kaz

3
내가 종종 볼 수있는 또 다른 이름은 getOrCreateSomething인데, 첫 호출에서만 생성 한 다음 무언가를 반환합니다
— Fabich

5
@aroth 사용 가능한 포트를 찾아서 반환하려고하지 않습니까? 아니면 그냥 잘못 써? ;)
— jpmc26

33

이름을로 바꿉니다 EnsureServerRunning.

완전히 명확하고 다시 시작하지 않아도 실행되고 있는지 확인합니다 (그렇지 않은 경우).

(대체 : StartServerIfNotRunning?)


1
대부분의 발신자는 통화 후 서버가 실행 중일뿐입니다. 그것이 달성되는 방법, 그들은 상관하지 않습니다.
— gnasher729

29

실제로 디자인 패턴은 아니지만 메소드를 dem 등원 이라고 부릅니다 . 일반적으로 원격 통화를 지칭하는 용어가 사용되지만 설명은 사용자의 작업과 일치하는 것 같습니다.

dem 등식 방법. 또한 메소드는 "오류 또는 만기 문제를 제외하고"N> 0 동일한 요청의 부작용이 단일 요청의 부작용과 동일하다는 점에서 "등가"속성을 가질 수 있습니다. ( W3.org에서 )

여기서 서버 부작용은 일단 메소드가 호출되면 http 서버가 시작된다는 것입니다. 나는 이것을하는 방법에 아무런 문제가 없다.

디자인 패턴이 필요하면 httpServer를 초기화 할 때 시작되는 싱글 톤으로 노출 할 수 있다고 생각합니다.


5
이 기능은되어 있지 멱등 번을 호출하면 HTTP 서버를 시작하고 전화를 두 번하지 않는 경우. 그것은 말 그대로 dem 등식의 반대입니다. 모든 호출이 새 http 서버를 시작한 경우 dem 등원 입니다.
— Polygnome

36
@Polygnome Wikipedia는 dem 등식 을 일반적으로 Nick의 설명과 일치하는 f (f (x)) = f (x)로 정의합니다 . 여기서 함수 입력 및 출력은 암시 적 서버 상태가되므로 "서버가 실행 중"상태는이 함수의 고정 점이됩니다. 어쩌면 나는 Wikipedia 기사를 오해하고있을 것입니다. 다른 참조에 연결할 수 있습니까?
— amon

16
@Polygnome :이 답변은 정확합니다. dem 등원 (Idempotency)은 한 번 이상 호출해도 중요하지 않은 함수를 나타내며 결과는 항상 동일하게 유지됩니다. 결과는 함수 호출 횟수와는 독립적으로 http 서비스를 실행하는 것입니다.
— Doc Brown

14
혼란은 핵심에서 dem 등성이 함수에 적용되는 수학적 개념이라는 사실에서 비롯됩니다. 정의는 훌륭하고 단순하며 순수한 기능적 언어에서도 잘 작동합니다. 부작용을 도입하자마자 복잡해집니다. 함수를 (암시 적) 인수와 출력으로 함수를 실행하는 환경을 고려해야합니다. 함수에 대한 추가 호출로 해당 상태가 수정되지 않으면 dem 등원이며 그렇지 않으면 그렇지 않습니다. 이 경우 관련 상태는 "http 서버 실행 중"이므로이 기능은 dem 등원입니다.
— Voo

10
@Polygnome 죄송합니다. 잘못되었습니다. dem 등수 (Idempotent)는 요청이 한 번 또는 여러 번 실행되는지에 관계없이 동일한 효과를 나타냅니다. 요청의 N 중복이 수신 된 경우 N http 서버를 시작하는 것이 반드시 dem 등하 지 않습니다.
— Kaz

7

이 구현 된 것과 같은 도구를 , startHttpServer당신은 가장 간단한 부드럽고 만들려고 노력한다 원활한 사용하는 ...

함수의 논리

기술적으로, 분할로 startHttpServer의 로직 2 개 기능에 와 그들을 호출 별도로 , 모든 당신입니다 않는 것을 이동 startHttpServer 의 ' 멱등을 당신이하는 일이다 (제 기능을 모두 논리를 포장하지 않는 한, 또한 ... 대신 두 함수를 호출하는 코드로 startHttpServer우선), 이것은 건조하지 않은 코드를 작성하여 호출 해야하는 모든 곳에서 기하 급수적으로 복제합니다 startHttpServer. 간단히 말해서 함수 자체 startHttpServer 를 호출해야 isHttpServerRunning합니다.

내 요점은 다음과 같습니다.

  • isHttpServerRunning어쨌든 독립적으로 필요할 수 있기 때문에 기능을 구현하십시오 ...
  • 그에 따라 다음 조치를 정의 startHttpServer하는 데 사용 isHttpServerRunning하도록 구현 하십시오 .

여전히이 startHttpServer함수의 사용자에게 필요한 값 을 반환 할 수 있습니다 . 예 :

  • 0 => 서버 시작 실패
  • 1 => 서버 시작 성공
  • 2 => 서버가 이미 시작되었습니다

함수의 이름

우선 , 사용자 의 주요 목표 는 무엇입니까? HTTP 서버 를 시작 하려면 ?

기본적으로 이미 시작된 무언가 AKA를 시작하려고해도 아무런 문제가 없습니다 1*1=1. 따라서 적어도 나에게 그것을 " ensureHttpServerIsRunning" 라고 부르는 것은 중요하게 필요하지 않은 것 같습니다. 나는 함수의 이름이 얼마나 길고 자연스럽고 기억에 남는 지에 대해 더 관심이 있습니다.

이제 후드에서 함수가 어떻게 작동하는지 자세히 알고 싶다면 해당 문서 또는 코드 소스가 있습니다. 라이브러리 / 프레임 워크 / API 등의 다른 함수와 같습니다.

당신은 배울 당신이 동안 한 번 기능을 쓰기 그것을 여러 번 ...

어쨌든, 나는 startHttpServer보다 짧고 간단하며 명시 적 ensureHttpServerIsRunning입니다.


1
특히이 방법은 루트 디렉토리, 보안 설정, 포트 번호와 같은 일부 구성 인수를 취해야하기 때문에 여기서는 "시작"에 100 % 익숙합니다.
— user949300

@ user949300 : "ensureHttpServerIsRunning"의 호출자는 구성, 루트 디렉토리 등을 신경 쓰지 않습니다. 이것이 구현하는 사람의 사업입니다.
— gnasher729 4

2
@ gnasher729 http 서버가 싱글 톤이라고 가정합니다. 싱글 톤은 악하다. 그리고 여기서는 부적절 할 수 있습니다. 여러 포트에 여러 서버를 쉽게 가질 수 있습니다. 실제로 하나의 http 서버 만있는 경우이 전체 방법은 IMO, 잘못된 디자인입니다. 프로그램을 초기화 할 때 서버를 한 번만 시작하는 것이 좋습니다.
— user949300

2

동료 startHttpServer가 너무 많은 일을하고 있다고 생각합니다 .

  • 서버가 이미 실행 중인지 확인
  • 필요한 경우 서버를 시작합니다.

그것들은 코드와 관련이없는 두 부분입니다. 예를 들어 데스크톱 응용 프로그램이 시작될 때 이미 실행되고 있지 않은지 확인해야하는 상황이 비슷합니다. 앱 인스턴스를 처리하는 코드의 일부 (예 : mutex 사용)와 응용 프로그램 메시지 루프를 시작하는 코드가 있습니다.

이것은 하나의 방법이 아니라 적어도 두 가지 방법이 있어야 함을 의미합니다 .

  • isHttpServerRunning: boolean
  • startHttpServer

응용 프로그램 진입 점은 첫 번째 메서드를 호출 한 다음 반환 값이 인 경우 두 번째 메서드를 호출합니다 false. 이제 모든 방법은 한 가지 일만하고 이해하기 쉽습니다.


¹ 서버가 이미 실행 중인지 알아야하는 논리가 너무 복잡한 경우 여러 방법으로 분리해야 할 수도 있습니다.


21
이제 두 함수를 호출하는 다른 두 가지 작업을 수행하고 함수를 개별적으로 노출하면 경쟁 조건이 발생할 수 있습니다. 무료 점심은 없습니다.
— whatsisname

1
그것이 동료에게 너무 많은 경우 행운을 빕니다.
— gnasher729

@ gnasher729 :이 답변은 귀하의 의견과 모순되지 않습니다-그 반대의 경우, 방법의 이름을 바꾸는 방법과 두 가지로 나누는 것을 결합하는 것이 좋습니다. 그리고 실제 코드가 보이지 않는 한 코드가 얼마나 복잡한 지 모릅니다.
— Doc Brown

10
이 답변은 추상화와 DRY에 반대하는 것 같습니다. startHttpServer코드에서 둘 이상의 장소를 호출 하면 어떻게 됩니까? 여러 줄의 유사한 줄을 어디에서나 복사하여 붙여 넣어야합니까? 모든 기능으로이 작업을 수행해야합니까? 곧 당신은 프로그램이 무한한 크기가 될 것입니다.
— JacquesB

3
이 방법의 첫 번째 부작용은 startHttpServer방법 의 시작이 대략 다음과 같다는 것 if (isHttpServerRunning()){ return; }입니다. "http 서버가 이미 실행중인 경우 시작하는 것이 유효하지 않다"는 비즈니스 규칙을 주장하지만 해당 규칙을 시행 할 다른 사람의 책임을지게합니다. 전화 할 수있는 모든 위치에서 임시로 반복해서 startHttpServer.
— aroth

2

언어를 지정하지 않기 때문에 JavaScript에서 많은 라이브러리에는 "한 번"기능 ( 예 : Underscore)이 있습니다. 따라서 익숙한 경우 "한 번"패턴이라고하고 메소드 이름을 바꾸십시오.

"캐싱"또는 "게으른 평가"라는 용어가 Java에서 더 많이 나옵니다. "등 전성"은 기술적으로 정확하고 esp. 더 기능적인 배경이 있다면.


서버를 중지 할 수 있으면 "한 번"이 아닐 수 있습니다.
— gnasher729 4

@ gnasher729. 거의 사용되지 않는 restartHttpServer()방법을 상상할 수 있습니다. 그러나 그만두십시오 -유스 케이스는 무엇입니까? 산발적 인 연결 실패를 좋아합니까? :-)
— user949300

HTTP 서버가 프로그램 외부의 외부에 의해 중지되었을 수 있기 때문에 HTTP 서버를 중지하는 유스 케이스가 필요하지 않습니다. HTTP 서버가 segfaulted 및 사망했을 수 있으며, 관리자가 수동으로 중지했을 수 있습니다. 등
— 데이브 Sherohman

데이브, 충돌은 "예외적"이므로 처리해야합니다. 게다가 충돌이 언제 라도 발생할 수 있기 때문에 코드의 모든 줄이되어야하는 것은 ensureRunning()아닙니까? :-) 관리자가 중지하면 관리자가 무언가를 수정하거나 수정하려고하는 동안이 다른 코드가 지속적으로 다시 시작되면 엄청나게 성 가실 수 있습니다. 코드가 아닌 관리자가 다시 시작하도록합니다.
— user949300

-2

선호합니다 startHttpServerIfNotIsRunning.

이런 식으로 조건은 메소드 이름에 이미 명확하게 언급되어 있습니다. Ensure또는 makeSure그것이 기술적 인 표현 아니므로, 나에게 조금 모호한 것 같다. 무슨 일이 일어날 지 정확히 알지 못하는 것 같습니다.


나는 당신이 원어민이 아니라고 가정하고 있습니까? 때문에 보장하는 것은 우리가 가고있는 무슨의 정확한 정의를 가지고있다. 그러나 여전히 문서와 API가 영어 원어민 수준을 이해할 필요가 없어야한다는 것이 합리적입니다.
— Voo

1
고마워 난 정확히 무슨 Ensure뜻이 아니야 . 나는 여전히 기술적 인 표현으로이 단어를 좋아하지 않습니다. Ensure인간입니다. 시스템은 아무것도 보장 할 수 없으며,해야 할 일만 할 것입니다.
— Herr Derb

2
@Voo-나는 원어민이며 어떤 의미가 있는지 잘 모르겠습니다.
— Jonathan Cast

여기에 게시하는 모든 사람이 인터넷에 액세스 할 수 있기 때문에 그들이 무엇을 의미하는지 확실하지 않은 경우 왜 '확보'의 정의를 찾지 않습니까? 약간의 사소한 ... 많은 사람들이 그 단어들 중 하나를 사용하는 것이 실수로 '법적'책임을지는 반면 다른 하나는 그렇지 않다는 것을 깨닫지 않고 'Ensure'와 'Assure'의 사용법을 서로 바꾸어 놓았습니다.
— 덩크

@jcast : 정말요?
— gnasher729 4

-3

동료가 당신에게 말한 것은 그 방법을 쓰는 사업이 없다는 것입니다. 이미 여러 번 쓰여졌으며 글을 쓰는 것보다 낫습니다. 예를 들면 다음과 같습니다. http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html

아키텍처 관점에서 볼 때 웹 서버를 관리하는 임의의 코드 비트를 갖는 것은 악몽입니다. 서비스를 관리하는 것이 독점적으로 코드가하는 것이 아니라면. 그러나 당신이 monit (또는 kubernetes 또는 ...)을 쓰지 않았다고 생각합니다.


2
언어는 Java이며이 방법은 독립 실행 형 Jersey 응용 프로그램에서 회색 임베디드 서버를 시작하도록 설계되었습니다. 나는 당신에게 많은 맥락을 제시하지 않았기 때문에 당신의 의견의 정확성을 잘못 판단 할 수는 없지만 진술을 많이 가정했습니다. 서버를 시작하기 위해 부두 또는 그리즐리를 호출하는 방법을 사용하는 것이 좋습니다.
— John Calcote

1
자체 호스팅 HTTP 서버를 포함하여 API를 제공하는 수백만 개의 비즈니스 응용 프로그램이 있습니다. 그리고 그 모두는 데, 보안 설정 등을 사용할 포트에 바인딩하는 데 실제로 사용하고있는 라이브러리를 설정하고 같은 어떤 인터페이스로 정보를 제공하는 매우 간단한 코드가 필요합니다 startServer기능 또는 아무것도 드문 일 뿐이다 유사하다 . 그렇다고해서 아주 세부적인 내용을 쓰지는 않습니다.
— Voo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.