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


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.