-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Refactor Internal module #1772
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
base: main
Are you sure you want to change the base?
Refactor Internal module #1772
Conversation
I believe the code that used callback_names was removed in 7cfa233
@items.key?(name) | ||
end | ||
|
||
def reset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now this class has both clear
and reset
, which redefines the ivar or calls clear
on it. Should we call clear
instead of reset
? I don't have a strong opinion on either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh good question 🤔 I implemented the #reset
method to break up behavior previously found in Internal#reset_configuration
; in doing so, I had overlooked that there was a #clear
here.
At the outset of considering the two methods, I don't have a strong opinion for using one over the other. I do believe we should normalize and standardize things for clarity.
- Ruby core classes like
Hash
andArray
have a#clear
method.- So a
#clear
method would seem to be a more idiomatic name to use.
- So a
- the performance difference between
Hash.new
andHash#clear
is likely negligible for most use cases. I'm not quite clear on what the impact on garbage collection would be. I'll assume any impact there is also negligible. - Considering the behavior nuances between the two methods: nothing outside of the Registry should be keeping a reference to the
@items
ivar.- So in this regard, I think either
#reset
or#clear
is fine to use. - When
Hash#clear
is invoked, the hash itself is returned. YetRegistry#clear
doesn't return self, but the result of@items.clear
(which is@items
). It is theoretically possible for something to callRegistry.clear
and then store a reference to the hash that's referenced by@items
. - This is relevant because when using
Registry#clear
, all references to the hash value will be cleared. Registry#reset
, on the other hand, sets@items
to be a new Hash, and all references to the previous hash will remain unaffected.- once again, however, nothing should be keeping a reference to
@items
and we don't do this inside FactoryBot.
- So in this regard, I think either
∴ I'd go with #clear
over #reset
# create a new hash
irb(main):001> a = { a: 1 }
=> {a: 1}
# set b as a reference to the hash after it is cleared
irb(main):002> b = a.clear
=> {}
# a and b now reference the same hash value
irb(main):003> a[:c] = 3
=> 3
irb(main):004> a
=> {c: 3}
irb(main):005> b
=> {c: 3}
# setting a to be a new Hash leaves be unaffected
irb(main):006> a = { b: 2 }
=> {b: 2}
irb(main):007> a
=> {b: 2}
irb(main):008> a.clear
=> {}
irb(main):009> a
=> {}
irb(main):010> b
=> {c: 3}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it overall. There are more module variables to think about now, but I think it's worth it.
I experimented with refactoring the
FactoryBot::Internal
andFactoryBot::Configuration
code:Internal
had to reach intoConfiguration
to access the registry instances and other config state. These methods also had low cohesion as they all used distinct subsets of the configuration state.Internal
module remains as a proxy/facade/aggregated type interface to minimize the impact on other modules throughout FactoryBotConfiguration
class and create an instance of it.Constructor#initialize_with
was a alias/delegation ofDefinition#define_constructor
soinitialize_with
is now an alias inside theDefinition