이 게시물은 "FORUM PHP 2024"에서 Gina Banyard의 기술 강연에서 많은 영감을 받았습니다.
몇 가지 동의어부터 시작해 보겠습니다.
Google에서 'PHP 모나드'를 검색하면 함수형 프로그래밍, 바인딩, 스택, 난해한 수학(예: 펑터, 모노이드)과 같은 다른 개념이 빠르게 등장합니다.
무서워하지 마세요.
기본적으로 모나드는 다양한 방식으로 구현될 수 있는 패턴입니다.
실행할 작업이 있는 경우 평소처럼 사용자 정의 개체와 도우미를 정의하기만 하면 됩니다.
그렇다면 대체 컨셉을 고민할 이유가 무엇인가요?
IMHO, 효율성을 유지해야 하기 때문에 여전히 좋은 질문이지만 고전적인 접근 방식에는 공통된 제한 사항이 있습니다.
모나드는 선택적(또는 아직 사용할 수 없는) 값을 더 일관되게 처리할 수 있습니다.
최신 프로젝트에는 정적 분석 도구가 포함되어 있지만 PHP 예외는 입력되지 않습니다.
즉, 도구는 함수 서명에서 예외를 감지할 수 없으므로 코드가 예외를 올바르게 처리하는지 확인할 수 없습니다.
이를 테스트하기 위해 일반적으로 개발팀에서는 기능 테스트를 작성하지만 정적 분석을 통한 조기 탐지가 더 안정적일 것입니다.
출처: "Les Exception : le trou dans la raquette du typage"(fr)
Monads를 사용하면 모든 경우에 형식화된 개체를 얻을 수 있으므로(예: FileErrors::AccessDenied) 오류가 시스템에 입력됩니다.
강력한 로깅 시스템을 구축하는 것은 어려울 수 있습니다. 문자열과 호출을 복제하는 것은 쉽습니다.
모든 것을 하드 코딩하는 대신 log()라는 사용자 정의 도우미를 정의하여 프로젝트의 모든 곳에서 사용할 수 있습니다.
이는 코드를 DRY로 유지하는 것을 목표로 하지만 특정 경우에는 더 복잡한 기능을 구성 허용하지 않을 수도 있습니다.
기능적 접근 방식은 이러한 전역 도우미를 사용하는 것으로 구성되지 않습니다. 대신, 다른 기능을 래핑하기 위해 Monad를 구현하는 것이 좋습니다.
final class LoggerMonad { public function __construct( public mixed $data, public array $logs = [], ) {} public function bind(callable $fn) { $resultLoggerMonad = $fn($this->data); return new LoggerMonad( $resultLoggerMonad->data, [...$this->logs, ...$resultLoggerMonad->logs], ); } } function loggify(callable $fn): Closure { return function ($value) use ($fn) { $name = (new ReflectionFunction($fn))->name; $log = [ 'Running '. $name .'('. var_export($value, true) .')' ]; return new LoggerMonad($fn($value), $log); }; }
그런 다음 loggify 래퍼를 다음과 같이 사용할 수 있습니다.
function add2(int $v): int { return $v + 2; } function square(int $v): int { return $v * $v; } function multi3(int $v): int { return $v * 3; } function logIt($value, callable ...$fns) { $logging_fns = array_map(loggify(...), $fns); $monad = new LoggerMonad($value); foreach ($logging_fns as $fn) { $monad = $monad->bind($fn); } return $monad; } print_r(logIt( 3, add2(...), square(...), multi3(...) ));
출처: Gina Banyard의 "Monades simplement"(fr)
?? 자기야 아프지 마
모나드는 객체와 함수를 포함한 모든 유형의 값을 래핑하기 위한 것입니다.
다른 래핑 시스템과 마찬가지로 이 값을 입력으로 사용하는 생성자(~ 클래스)와 구현하려는 패턴에 따라 고유한 목적을 갖는 일부 메서드를 찾을 수 있습니다.
그러나 모든 모나드는 바인드 기능을 포함합니다. 이름에서 알 수 있듯이 여기에 값(또는 콜백)이 전달됩니다.
이러한 콜백에서 무슨 일이 일어나든 모나드는 이를 래핑합니다. 이는 값을 장식하고 코드를 리팩터링하는 강력한 방법인 것 같습니다.
구현에 따라 확실히 다르고, 처음에는 길을 잃기 쉽습니다.
그러나 이 대체 접근 방식은 if 블록의 양을 크게 줄이고 반환 값을 보다 일관되게 만들 수 있습니다.
final class LoggerMonad { public function __construct( public mixed $data, public array $logs = [], ) {} public function bind(callable $fn) { $resultLoggerMonad = $fn($this->data); return new LoggerMonad( $resultLoggerMonad->data, [...$this->logs, ...$resultLoggerMonad->logs], ); } } function loggify(callable $fn): Closure { return function ($value) use ($fn) { $name = (new ReflectionFunction($fn))->name; $log = [ 'Running '. $name .'('. var_export($value, true) .')' ]; return new LoggerMonad($fn($value), $log); }; }
출처: fp4php - 모나드
이제 PHP 모나드에 대해 조금 더 알게 되기를 바랍니다.
물론 단지 목적만으로 프로젝트에 화려한 디자인 패턴을 추가해서는 안 됩니다.
게다가 요점을 놓치기 쉽고 오류 처리와 같은 매우 구체적인 측면에 집중하는 것은 완전히 새로운 패러다임입니다.
그러나 새로운 접근 방식을 발견하는 것은 여전히 신선한 일입니다. 고정관념에서 벗어나 생각해야 합니다.
위 내용은 PHP: 모나드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!