この記事は「Elixir Advent Calendar 2023」21日目の記事です
東京にいるけどfukuokaexのYOSUKEです。
普段は 合同会社TheWaggle で教材開発・システム開発・研修講師などマルチに活動してます。
このシリーズでは、文系ですらない、体育会系でも始められるプログラミング学習 というテーマで元自衛官だった僕が
自衛官からエンジニアになってもらいたいという気持ちを込めて、普段は大人しいですが、このコラムシリーズでは、あえて、体育会系のノリで、貴様ら理屈で覚えるなら体で覚えろ!というノリで書いてみたいと思います。
なので、初学者向けですが、理論は後回し、まずは動かして体感しろってノリの第21回目です。
それでは、いくぞ!
リファクタリング
defmodule TNT do
def create_c4({"RDX", rdx},{"ポリイソブチレン", polyisobutylene},{"モーターオイル", motorOil},{"セバシン酸ジオクチル", dioctylSebacate},{"ガソリン", gasoline}) do
{ g , ml } =
[ rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline ]
|> Enum.split(-1)
g_results =
Enum.map(g, &(String.codepoints(&1) |> List.delete_at(-1) |> List.to_string() |> String.to_float()))
ml_result = "25ml" |> String.codepoints() |> List.delete_at(-1) |> List.delete_at(-1) |> List.to_string() |> String.to_integer()
g_results ++ [ml_result]
end
end
貴様らが作ったものを改良して前回、以下のように修正した。しかし、まだまだ改良する余地がある。
defmodule TNT do
def create_c4({"RDX", rdx}, {"ポリイソブチレン", polyisobutylene}, {"モーターオイル", motorOil}, {"セバシン酸ジオクチル", dioctylSebacate}, {"ガソリン", gasoline}) do
materials = [rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline]
Enum.map(materials, fn material ->
# 単位を取り除く
numeric_part = material
|> String.trim_trailing("g")
|> String.trim_trailing("ml")
# 小数点の有無に基づいて数値に変換
if String.contains?(numeric_part, ".") do
String.to_float(numeric_part)
else
String.to_integer(numeric_part)
end
end)
end
end
さらに改良したのが以下のコードだ。この改良にはいくつかのポイントがある。また、さらに貴様らが知らない技術が盛りだくさんだ。 また、今回から少しづつ教えてやるから、貴様らのそのnil頭によーく、詰め込んでおけ!
貴様らが書いたTNTモジュールはまるでクソコードだったが、それを改良したコードもまだまだ無駄が多い! そう、まるで新兵のように未熟だ。今からこのひどいコード、いわば新兵から熟練の兵士に鍛えあげてやる!
ダメなコード部分
単位の取り除き方が雑だ:String.trim_trailing/2を二回も使ってるだと?!貴様、それは無駄だ!もっと効率的な方法がある。
重複するロジック:String.contains?/2 で小数点の有無を確認し、それに基づいてString.to_float/1 か String.to_integer/1 を使ってる。このロジック、何度も使ってるなら別の関数に切り出せ!
改良点
単位を取り除く効率的な方法:正規表現を使って一度に単位を取り除け。String.replace/3 がお前の友だ。
数値変換のロジックを別関数に切り出せ:小数点の有無に基づく変換処理を繰り返し使うなら、それは別の関数にしろ。コードの重複は敵だ!
これらを踏まえて、改良したコードがこれだ。
defmodule TNT do
def create_c4({"RDX", rdx}, {"ポリイソブチレン", polyisobutylene}, {"モーターオイル", motorOil}, {"セバシン酸ジオクチル", dioctylSebacate}, {"ガソリン", gasoline}) do
materials = [rdx, polyisobutylene, motorOil, dioctylSebacate, gasoline]
Enum.map(materials, &convert_material_to_numeric/1)
end
defp convert_material_to_numeric(material) do
numeric_part = String.replace(material, ~r/[gml]/, "")
convert_to_numeric(numeric_part)
end
defp convert_to_numeric(numeric_part) do
if String.contains?(numeric_part, ".") do
String.to_float(numeric_part)
else
String.to_integer(numeric_part)
end
end
end
このように新兵のようなコードをを鍛えることをリファクタリングという!
常に、貴様らは最初から熟練の兵士のようなコードは書けない! だが、新米だろうが、熟練だろうが、まずは結果を出せれば良い! 結果を出してから今回のようにリファクタリングをして行けばいいんだ! わかったな!
- 教官! 何やら見たことないコード が沢山あります!
いいだろう! 次回以降で新たに出てきたコードを解説してやろう。 それでは 次回 Part22でまた会おう!