'Refactoring a Function in Elixir'블로그 포스터 읽어주세요.
오늘 제가 Elixir의 블로그를 검색했을 때 Dock Yard에서 보내온'Refactoring a Function in Elixir라는 블로그를 발견했습니다. 내용에 대해 접촉하고 싶습니다.
뭐라고 써있어요?
Designing Elixir Systems with OPP'라는 책의 Part.1에 적힌 디자인 원칙에 따라 간단한 게임 퀴즈의 팩스 예시를 총결하였다.
(이 책은 자주 볼 수 있어요. 영문판도 있고 읽을 가치도 높다고 생각해서 이 기사를 쓰면서 넘겼어요.😇)
아래의 기본 원칙에 따라 팩스를 진행한다.
제목.
# game.ex
def answer_question(%Game{current_question: current_question} = game, guess, user_name) do
case(current_question.mascot == guess) do
true ->
game =
game
|> increase_score_for_user(user_name)
|> check_for_winning_user(user_name)
|> Map.put(:current_question, get_random_question())
{:ok, game}
_ ->
{:error, :incorrect}
end
end
step1: Functions should be at single layer of abstraction
먼저 SLAP을 기준으로 수정합니다.
먼저, 맵.put에서 쓴 부분을 pipe와 연결된 다른 함수의 입도와 일치하도록 이름을 붙여 함수에 잘라냅니다.
수정되면 이쪽이야.
Map.put
Elixir의 데이터 구조는 간단한 처리로 쓴 함수select_question/1
.이에 따라 level 완비increase_score_for_userして、check_for_winning_userして、select_questionして...
의 경우.# game.ex
def answer_question(%Game{current_question: current_question} = game, guess, user_name) do
case(current_question.mascot == guess) do
true ->
game =
game
|> increase_score_for_user(user_name)
|> check_for_winning_user(user_name)
|> select_question() # add select_question() to the pipeline
{:ok, game}
_ ->
{:error, :incorrect}
end
end
defp select_question(game) do
Map.put(game, :current_question, get_random_question())
end
다음으로 수정case(current_question.mascot == guess) do
한 부분.이것도 "사용자 정답인가요?"이런 논리는 함수화되지 않았기 때문에 수정할 여지가 있다.'사용자의 대답'
Response
을 정리하고 구조체를 준비해 거기correct
에서 키를 만든다.correct에 correct?/2
의 결과를 입력하십시오.# response.ex
defmodule Response do
defstruct ~w[guess game user_name correct]a
def new(game, guess, user_name) do
%__MODULE__{
guess: guess,
user_name: user_name,
game: game,
correct: correct?(game, guess)
}
end
defp correct?(%Game{current_question: current_question} = game, guess) do
current_question.mascot == guess
end
end
이 구조체를 사용하여 게임의 논리를 개작한다.# game.ex
def answer_question(%Game{current_question: current_question} = game, guess, user_name) do
response = Response.new(game, guess, user_name)
case(response.correct) do
true ->
game =
game
|> increase_score_for_user(user_name)
|> check_for_winning_user(user_name)
|> select_question() # add select_question() to the pipeline
{:ok, game}
_ ->
{:error, :incorrect}
end
end
단번에 이 코드가'최초에 정확했는지 부정확했는지 알 수 있다.정답이 정확하지 않은 조건을 나누면increasescore_for_user→check_for_winning_user→select_question과 논리를 통해 일목요연하게 변했다.step2: Make decisions in function heads where possible
가능하면 조건 차이를 함수 헤더로 기술하는 방침으로 코드를 바꿉니다.
결론이 명확하게 쓰여 있는 코드.세 개의 동명 함수를 설명하고 패턴이 두 번째 파라미터와 일치합니다
guess(string)
%Response{correct: true}
%Response{correct: false}
# game.ex
def answer_question(%Game{current_question: current_question} = game, guess, user_name)
when is_binary(guess) do
response = Response.new(game, guess, user_name)
answer_question(game, response, user_name)
end
def answer_question(game, %Response{correct: true} = response, user_name) do
game =
game
|> increase_score_for_user(user_name)
|> check_for_winning_user(user_name)
|> select_question()
{:ok, game}
end
def answer_question(_game, %Response{correct: false} = response, _user_name) do
{:error, :incorrect}
end
코드가 유창하다.다만, 개인도 원래 케이스 코드를 즐겨 사용한다.업무 시스템 등에서 의견 차이 조건 자체에 강한 관심이 있다면 원래의 케이스가 코드를 읽을 때 한꺼번에 따라잡기 쉽다고 생각합니다.총결산
이것은 원칙을 폭로할 수 있는 좋은 블로그이다🎉
입도에 주의하고 적절한 명칭의 함수를 써야 한다.실수로 Enum과 Map을 단번에 다 써버렸어요. "어? 이 목록을 어떻게 처리하고 싶어요?"이것도 쉽게 이런 상태에 빠지게 한다(Elixir든 다른 언어든 그렇지만)
원리 원칙을 준수하고 테스트, 유지보수가 쉬우므로 가독성이 높은 코드를 쓸 수 있기를 바랍니다🚀
Reference
이 문제에 관하여('Refactoring a Function in Elixir'블로그 포스터 읽어주세요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/koga1020/articles/d1ac2beab15132텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)