Conversation
…rクラスとFileEntriesListクラスの機能がほぼ同じのため、EntriesListモジュールを作成し、共通化
07.ls_object/main.rb
Outdated
| require 'io/console' | ||
| require_relative 'ls' | ||
|
|
||
| LS_SHORT_WIDTH = IO.console.winsize[1] |
There was a problem hiding this comment.
こちらについてですが、画面のサイズを取得してshort_formatで出力する際の最大幅を取得しています
There was a problem hiding this comment.
なるほど、shortフォーマット用ということですね。
どちらかというと、「何に使うか?」よりも「何が入っているか?」の方がより気になるところなので画面のサイズという意味の変数の方が良いでしょう。
また、この値は環境によって違うので定数ではなく変数の方が良いですね。
07.ls_object/ls.rb
Outdated
|
|
||
| private | ||
|
|
||
| def parse_paths_and_options |
There was a problem hiding this comment.
こちらについて1点質問です。
parse_optionsとparse_pathsに分ける場合、parse_options⇒parse_pathsの順番で実行されない場合挙動がおかしくなってしまう認識です(オプションあり、引数無しの場合に何も表示されないなど)。
この場合でもメソッドを分割したほうがよろしかったでしょうか
There was a problem hiding this comment.
確かにそうですね。ここはメソッドにしてない人が多かったのでいつも気にしておらず、長過ぎるメソッド名を見て指摘した感じですね。
理想としては parse_pathsでオプションにあたるものを無視するようにするあたりですが、今の状況で順番が大事である旨をコメントしておくぐらいで良いと思います。
あとオススメするわけじゃないですが parse_input ぐらいの名前だったらスルーしてしまったかもしれません 😓
長い名前で and を付けてると 「このメソッド分けられそう!」って思っちゃうので。
07.ls_object/ls.rb
Outdated
| paths, options = parse_paths_and_options | ||
|
|
||
| @command = if options[:long_format] | ||
| LsLong.new(paths, options) |
There was a problem hiding this comment.
LongとShortは出力の形式が違うだけなのでLsCommand自体を継承した二つに分けるのはちょっとおかしいですね。
07.ls_object/file_entries_list.rb
Outdated
| class FileEntriesList | ||
| include EntriesList | ||
|
|
||
| attr_accessor :entries |
07.ls_object/entries_list.rb
Outdated
| @@ -0,0 +1,27 @@ | |||
| # frozen_string_literal: true | |||
|
|
|||
| module EntriesList | |||
There was a problem hiding this comment.
名前が Entriesの時点で rubyの慣習上、複数系は単数名のクラスの配列もしくは配列を保持するクラスになるので、Listは不要です。
07.ls_object/dir_entry.rb
Outdated
| require_relative 'entries_list' | ||
|
|
||
| class DirEntry | ||
| include EntriesList |
There was a problem hiding this comment.
DirEntryと FileEntriesList は両方とも file_entriesを持っていますが、どのように使い分けるのでしょうか?
There was a problem hiding this comment.
なるほど!
「任意のパスを指定できる」仕様は現状必須では無いはず
( https://bootcamp.fjord.jp/pages/ls-command で確認しました)
なのでいったん外してしまいましょう。
そのまま無しでもプラクティス的には良いですし、やるにしてもいったん外してオブジェクト指向的に整理してから追加した方が早そうですし。
cdf1a29 to
9c213ff
Compare
07.ls_object/file_entry.rb
Outdated
| 'directory' => 'd', | ||
| 'file' => '-', | ||
| 'link' => 'l' | ||
| }.tap { |h| h.default = '-' }.freeze |
There was a problem hiding this comment.
こちらに指摘いただいたのですが、3通り以外のファイルタイプに対応しておらず、3通り以外のものを指定されたときに'-'を表示するように設定いたしました。
#11 (comment)
There was a problem hiding this comment.
こちらせっかくなので下記の記事を参考に他のファイルタイプについても対応いたしました。
https://zenn.dev/universato/articles/20201202-z-mode
07.ls_object/file_entry.rb
Outdated
| # File::statのブロックサイズの単位は512bytesであるから変換する | ||
| block_size = stats.blocks * (512 / BLOCK_SIZE.to_f) | ||
|
|
||
| { type_and_mode: mode, nlink:, user:, group:, size:, mtime:, name:, |
There was a problem hiding this comment.
こうやって計算結果をhashに詰めて外部から参照できるんであればこのhashを作るメソッドと変わりません。
このFileEntryクラスに modeは? userは?と聞いて返ってくるようにしましょう。
cd1e3c0 to
3fa75b5
Compare
07.ls_object/file_entry.rb
Outdated
|
|
||
| require 'etc' | ||
|
|
||
| FILE_TYPE_LOOKUP = { |
There was a problem hiding this comment.
解決するための変数名ですが、LOOKUPだとちょっと違和感があります、意味的にはFOR_LOOKUPならわかるけど、ちょっと冗長だし、 FILE_TYPESとかSHORT_FILE_TYPESとかかなと思います。
07.ls_object/file_entry.rb
Outdated
|
|
||
| def initialize(path) | ||
| @path = path | ||
| @stats = File.lstat(@path) |
There was a problem hiding this comment.
細かいけど、 メソッドもstatだし statsだと配列かな?って思っちゃうので @stat の方が良いかと思います。
| @@ -0,0 +1,62 @@ | |||
| # frozen_string_literal: true | |||
07.ls_object/ls.rb
Outdated
| require 'optparse' | ||
| require_relative 'ls_command' | ||
|
|
||
| class Ls |
There was a problem hiding this comment.
このクラスはちょっと冗長かと思います。LsCommandかmainでやれば良いと思います。
07.ls_object/ls_command.rb
Outdated
| def initialize(paths, options) | ||
| @paths = paths | ||
| @options = options | ||
| @format = @options[:long_format] ? LsLong.new : LsShort.new |
There was a problem hiding this comment.
formatだと フォーマットの名前が入っていそうです。 formatするオブジェクトを入れるなら formatter の方が良いですね。
LsLong/LsShort も Formatterを最後に付けた方が良いですね。またついですが、 Lsは冗長なのでLongFormatter/ShortFormatterで良いと思います。
07.ls_object/ls_short.rb
Outdated
|
|
||
| require 'io/console' | ||
| class LsShort | ||
| def initialize(window_width = IO.console.winsize[1]) |
There was a problem hiding this comment.
デフォルト値を外から渡すケースは無いと思うので、 引数を無くして、initialize内で設定すれば良いと思います。
07.ls_object/ls_command.rb
Outdated
| def run | ||
| output = @directories.map do |dir_entry| | ||
| header = "#{dir_entry.path}:" if @directories.count > 1 | ||
| body = @format.run(dir_entry).to_s |
There was a problem hiding this comment.
formatするオブジェクトが runして 戻ってきたものを to_s する必要は無いはずです。

lsコマンド実装したもの
実装しなかったもの