Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor match finding (remove MatchFinder) #32

Merged
merged 10 commits into from
Aug 16, 2020
Merged

Refactor match finding (remove MatchFinder) #32

merged 10 commits into from
Aug 16, 2020

Conversation

matthewmcgarvey
Copy link
Member

@matthewmcgarvey matthewmcgarvey commented Aug 11, 2020

Summary

This change removes the MatchFinder class completely and moves the logic into the Fragment class. I believe this brings clarity to the codebase as the logic using the finder required passing in the fragment and all of the passed in information anyways and it was calling methods on the fragment. It also brought a fairly hefty speed boost.

By putting all this code together where it was previously separated, I'm hoping to find patterns in the codebase that can be extracted to provide further clarity. The ones that I am currently considering are:

  • I think it makes sense to make dynamic fragments extend fragments so that they can be treated the same way
  • Right now only the parent knows the path name of its children but it might be more clear to either move that down into the fragment that represents that path name or to have them in both.
    • That way I don't have to dig into the parent of a dynamic fragment to get its name.
  • Fragment#find updates a hash of params as it reduces over the path parts. I'm thinking of an alternative API where this find delegates to a find on its current fragment that handles a single path part and returns back a tuple of the matching fragment and the path part and after the reduce check if any of the matching fragments were dynamic to be up the params

Benchmark (with --release)

  • Before: 193 ms
  • After: 169 ms
  • Difference: 24 ms
  • Improvement: 12%

Copy link
Member

@paulcsmith paulcsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup and perf boost! Just a couple small things then LGTM!

Comment on lines +62 to +63
def initialize(@dynamic = false)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me nervous but I think you plan to extract a DynamicFragment right? If so then I think this is good for now and can be cleaned up in a later PR

Comment on lines +68 to +70
# params are a key value pair of a path variable name matched to its value
# so a path like /users/:id will have a path variable name of id and
# a matching url of /users/456 will have a value of 456
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 👍

params = {} of String => String
result = parts.reduce(self) do |fragment, part|
match = fragment.static_parts[part]? || fragment.dynamic_part.try(&.fragment)
return NoMatch.new if match.nil?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you refactor this to use implicit returns instead? I find them a bit tricky to work with and refactor since the behavior can change when extacted. For example if this this block of code inside the do/end were moved to a private method the early return would no longer work because it'd return from the new method and not this one.

end

payload = result.method_to_payload[method]?
return payload.nil? ? NoMatch.new : Match(T).new(payload, params)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return payload.nil? ? NoMatch.new : Match(T).new(payload, params)
payload.nil? ? NoMatch.new : Match(T).new(payload, params)

Comment on lines 102 to 104
def dynamic?
@dynamic
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do getter? :dynamic to define a getter :D It's a handy little macro!

@matthewmcgarvey
Copy link
Member Author

@paulcsmith Your changes have been implemented

Copy link
Member

@paulcsmith paulcsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you 😊

@paulcsmith paulcsmith merged commit 754f5ba into luckyframework:master Aug 16, 2020
@matthewmcgarvey matthewmcgarvey deleted the find-match-refactor branch August 16, 2020 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants