Elixir 중원 프로그래밍의 함정
16442 단어 elixir
이전에 우리는 거대한 각종 응용을 탐구했다.
이 섹션에서는 Elixir에서 메타 프로그래밍을 할 때 발생할 수 있는 일반적인 트랩을 심도 있게 살펴보겠습니다.
거대한 흔한 위험
official documentation:
Macros should only be used as a last resort. Remember that explicit is better than implicit. Clear code is better than
concise code.
모든 일에 원 프로그래밍을 사용하는 것은 매력적일 수 있지만, 항상 최선의 선택은 아닐 수도 있다.
이 시리즈의 Applications of Macros 부분은 매크로의 대다수 용례를 개술하였다.
그러나 매크로를 사용할 때는 매우 조심해야 한다.
매크로를 사용할 때 피해야 할 세 가지 공통 트랩을 살펴보겠습니다.
주: 이 요점들의 영감은 Metaprogramming Elixir에서 나온다.
1. 불필요한 함수를 매크로로 주입
매크로는 호출자에게 함수를 주입하는 데 사용할 수 있지만, 때로는 필요하지 않을 때도 있다.
다음 예를 살펴보겠습니다.
defmodule CalculatorTransformer do
defmacro __using__(_) do
quote do
def add(a, b), do: a + b
def subtract(a, b), do: a - b
def multiply(a, b), do: a * b
def divide(a, b), do: a / b
end
end
end
defmodule Hospital do
use CalculatorTransformer
def calculate_cost(suite, procedure) do
add(suite * 20, multiply(procedure, 5))
end
end
우리는 모듈 표지부에 대한 수요를 없애기 위해 각종 계산기 함수를 Hospital
에 주입할 것이다.그러나
add
과 multiply
의 사용은 현재 근거 없이 나타난 것 같다.이 코드는 의미를 잃어 처음 읽는 사람에게는 더욱 이해하기 어려워졌다.
코드의 의미를 보존하려면
CalculatorTransformer
을 일반 모듈로 정의하십시오.이 모듈은 import
에 Hospital
을 삽입하여 모듈 식별자를 제거할 수 있습니다.defmodule CalculatorTransformer do
def add(a, b), do: a + b
def subtract(a, b), do: a - b
def multiply(a, b), do: a * b
def divide(a, b), do: a / b
end
defmodule Hospital do
import CalculatorTransformer
def calculate_cost(suite, procedure) do
add(suite * 20, multiply(procedure, 5))
end
end
불필요한 함수를 만드는 것 외에 매크로는 모듈에 과도하게 주입할 수 있습니다.이것이 무엇을 의미하는지 토론해 봅시다.2. 매크로 과잉 주입 행위
Elixir가 호출 사이트에 매크로를 주입하면 비헤이비어가 과도하게 주입될 수 있습니다.
BaseWrapper
의 예로 돌아가겠습니다.만약 우리가
post?
의 해석 논리를 __using__
매크로에 남겨 두면 어떻게 될까요?defmacro __using__(opts) do
quote location: :keep, bind_quoted: [opts: opts] do
# ...
def post?(url, body) do
case post(url, body) do
{:ok, %HTTPoison.Response{status_code: code, body: body}} when code in 200..299 ->
{:ok, body}
{:ok, %HTTPoison.Response{body: body}} ->
IO.inspect(body)
error = body |> Map.get("error", body |> Map.get("errors", ""))
{:error, error}
{:error, %HTTPoison.Error{reason: reason}} ->
IO.inspect("reason #{reason}")
{:error, reason}
end
end
end
end
이런 방법에는 두 가지 문제가 있다.테스트
post?
을 통해 상속기를 테스트할 수 있으며 BaseWrapper
이 아니다.BaseWrapper
에 여러 명의 상속자가 있고 post?
의 전체 행위가 상속자에게 주입되기 때문에 우리는 각 상속자를 단독으로 테스트해야 한다.이는 상속자에 특정한 행위가
post?
의 행위를 수정하지 않도록 확보할 수 있다.그렇지 않으면 테스트 범위가 낮아질 수 있습니다.
불명확한 오류 보고.
post?
이 일으킨 모든 운행 시 오류는 BaseWrapper
이 아닌 계승기에 기록됩니다.post?
에 남겨 혼란을 초래할 수 있다.BaseWrapper
의 원시적인 실현은 대부분의 해석 행위를 포장기로 옮긴다.이런 실현은 더욱 간결하고 의미가 더욱 의미가 있으며 가독성이 더욱 강하다.이렇게 하면 다음과 같이 두 문제를 최소화할 수 있습니다.
post?
의 핵심 행위를 테스트할 때 모든 상속자가 아닌 BaseWrapper.parse_post
만 테스트한다.해석 프로세스의 모든 오류는
BaseWrapper
에 기록됩니다.참고:
location: :keep
은 비슷한 방식으로 작동합니다.경험의 법칙은 거대한 행위량을 최소화하는 것이다.
매크로가 필요한 정보/계산에 액세스/실행되면 나머지 동작을 매크로에서 옮겨야 합니다.
우리가 연구할 마지막 함정은 일반 함수가 충분할 때 매크로를 사용하는 것이다.
3. 일반 함수 대신 매크로 사용하기
비록 그것들의 기능은 강하지만, 항상 매크로가 필요한 것은 아니다.어떤 경우 일반적인 함수로 매크로의 행동을 대체할 수 있습니다.
컴파일할 필요가 없을 때 정보(또는 매크로 실행 계산)의 동작이 매크로에 배치된다고 가정합니다. 예를 들어,
defmodule Foo do
defmacro double(x) do
quote do
doubled = unquote(x) * 2
doubled
end
end
end
defmodule Baz do
require Foo
def execute do
Foo.double(3)
end
end
iex(1)> Baz.execute
6
여기서 double
은 일반 함수를 쉽게 대체할 수 있다.그것의 행위는 컴파일할 때 정보도, 매크로로 계산할 필요도 없다.그것은
Baz
을 주입하고 execute
을 호출할 때 일반 함수와 같이 평가할 것이다.defmodule Foo do
def double(x), do: x * 2
end
defmodule Baz do
def execute, do: Foo.double(3)
end
iex(1)> Baz.execute
6
보시다시피 double
을 매크로로 정의하는 것은 일반 함수에 비해 아무런 이익이 없습니다.Elixir의 메타 프로그래밍:추가 읽기
우리는 마침내 Elixir 중원 프로그래밍에 대한 조사를 끝냈다.
기억해라: 위대한 힘에는 위대한 책임이 수반된다.원 프로그래밍을 잘못 사용하면 다시 너를 해칠 수 있으니 조심해서 행동해야 한다.
이 시리즈는 원 프로그래밍과 그 복잡한 점을 간단명료하게 설명하는 데 목적을 두고 있지만, 결코 이 주제의 성경이 아니다.
아주 좋은 자원이 많아서 Elixir 중원 프로그래밍에 대한 지식을 더 많이 배울 수 있습니다!다음은 다음과 같습니다.
서면 지침서
Understanding Elixir Macros - The Erlangelist *
Metaprogramming Elixir *
읽어주셔서 감사합니다. 다음에 또 만나요!
또한, 출판 후 바로 장생불로약 연금술 게시물을 읽고 싶다면 subscribe to our Elixir Alchemy newsletter and never miss a single post!으로 전화하세요
가호우는 샤오홍점 싱가포르에서 온 개발상이다!그는 각종 기술을 보완하는 것을 좋아했고, 이미 불로장생약과 바둑을 약 1년 동안 사용했다.그의 프로그래밍 여행에 따라 his blog과 전화를 걸었다.
Reference
이 문제에 관하여(Elixir 중원 프로그래밍의 함정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/appsignal/pitfalls-of-metaprogramming-in-elixir-aj9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)