00:00:10.480
Hello everyone! My name is Andy Andrea, and I have considerable experience working as a Ruby developer.
00:03:58.920
In Ruby and Rails development, we often face challenges where methods or classes may differ slightly in terms of functionality.
00:04:04.040
For instance, different methods may raise various errors or warnings, leading to side effects that can impact performance. Some functions operate fully in the database, while others work entirely in memory. It's essential to understand their performance implications when deciding on the approach.
00:04:30.759
This often comes down to performance considerations. Sometimes, offloading work to the database is beneficial, but if you've already loaded data, it might be more efficient to operate in memory.
00:04:41.400
When looking at methods, the difference between bang and non-bang methods, or place allocation versus object allocation, can be significant. These differences can affect garbage collection or result in unintended modifications.
00:05:06.080
The aspects covered so far have focused on performance, but there are many additional factors that can differentiate methods. I also want to touch upon general usage semantics, which often guide how we choose to implement these methods.
00:05:17.560
Of course, linter rules play a role, but I won't delve into those due to their complexity and variability.
00:05:32.400
This talk will specifically focus on methods and classes that might seem similar at first glance, and we'll explore their distinctions.
00:05:50.960
We'll begin with a relatively simple example compared to the later ones. This involves the `cover` and `include` methods that we can apply to the Range class.
00:06:05.520
These two methods serve similar functions, but they have differences worth noting for our discussion. `include` is older, and while it might not have a significant effect on our day-to-day decisions, it’s important to recognize some Ruby applications are still using older versions.
00:06:31.319
In this talk, we'll benchmark these methods using Ruby 3.3.0. Different environments may yield different results, so keep that in mind.
00:06:51.000
Comparing the performance of `range.cover` versus `range.include`, using the range of letters from A through Z, we notice that `cover` operates about twice as fast as `include`. This performance metric is less critical with small ranges but becomes significant with larger ranges.
00:07:36.319
For example, a range like A..ZZ would drastically affect performance, with `include` dropping to just 27.7 iterations per second compared to `cover`.
00:08:08.920
On the general usage side, both methods return true for values within the range but false outside. This makes them appear quite similar.
00:08:36.360
The difference becomes notable when we call these methods on non-numeric ranges. When we test strings, we can see that `cover` may indicate that certain values are technically covered by the range even if they aren't within it.
00:09:05.200
Understanding when `include` raises errors for endless or beginningless ranges is essential as it could lead to unexpected behaviors. In contrast, `cover` will return a boolean without raising exceptions in these cases.
00:09:24.640
Another differentiation is in how `include` fully evaluates the range while `cover` only checks the endpoints, which contributes to its performance advantage.
00:09:47.640
This helps to illustrate how different methods can serve similar purposes while exhibiting unique behaviors that can affect performance and usability.
00:10:08.880
Next, we'll move to regular expression matching, which provides several options for pattern matching in Ruby.
00:10:30.000
Initially, I found the need for a method that returns a simple boolean rather than a numeric value, and I was delighted when Ruby 2.4 introduced the `match?` method.
00:10:54.320
As we analyze the performance of regular expression methods, we identify the varying return values across methods like `match`, `scan`, and others.
00:11:10.640
It's important to understand how these methods can affect our code, especially when we consider side effects from global variable settings.
00:11:48.320
For instance, every regular expression call (except for `match?`) sets a range of global variables that can lead to issues, particularly if developers are unaware of them.
00:12:07.560
Designing code that’s readable involves recognizing the implications of using these global variables and finding ways to mitigate their effects.
00:12:27.000
Now let's touch on the nuances of the `method` and `not implemented error` in Ruby.
00:12:42.120
A `no method error` typically arises when invoking a method on a nil object, whereas a `not implemented error` occurs with unsupported system calls. Their different behaviors are crucial to understanding error handling in Ruby.
00:13:05.360
An interesting aspect of `not implemented error` is its use among developers to mock interfaces without actual implementations, indicating where future code should go.
00:13:36.360
When rescuing these errors, note that a typical rescue will catch all standard errors but will not catch every instance of `not implemented error`.
00:14:03.160
Moving on, let's talk about monkey patching with defined method classes.
00:14:24.960
This technique enables developers to inject additional methods into classes or modules, enhancing functionality without needing to alter their original structure.
00:14:42.960
While you might be used to monkey patching as the conventional approach, there are also alternatives like defining methods through class variables.
00:15:01.440
The subsequent part of our dialog will explore performance differences with these methods; surprisingly, monkey patching proved to be one of the seemly fastest solutions.
00:15:21.040
With options available to delegate methods, we can also delve into Active Support’s delegate method.
00:15:42.200
Active Support's functionality can be beneficial, but it demands having the Active Support library, which might not always be accessible in a standard Ruby script.
00:16:09.160
The distinctions between global and targeted delegation highlight the differences in these approaches. Depending on how they are structured and used, performance can vary.
00:16:30.000
For example, when using `define_method`, you are given more control and flexibility, enabling specific outcomes while still leveraging Ruby's dynamic nature.
00:17:00.000
This brings us to the comparison of delegation methods; there are various options that serve similar purposes but can have distinctly different performance impacts.
00:17:27.960
Another area of exploration includes defining methods within the context of Ruby, indicating the need to thoroughly evaluate the efficiency of the chosen approach.
00:17:51.480
Finally, let’s discuss how method calls using different expressions perform under various conditions.
00:18:18.040
Watching the performance metrics in action can paint a clearer picture of how seemingly subtle differences can create significant performance variations.
00:18:43.360
The exploration of method calls leads us to consider other inventive ways of invoking methods, even including the 'smearing' of method calls—an artistically humorous notion.
00:19:06.720
As we wrap up our exploration of Ruby methods and classes, it’s essential to understand the importance of clarity and maintainability while writing code.
00:19:31.920
Invoking methods through unusual syntax or employing complicated mechanisms may lead to confusion, and the code's intention can become obscured.
00:19:56.320
This serves as a reminder—when coding, simple and clear function calls often lead to better performance and ultimately, increased maintainability.
00:20:18.480
I hope this analysis has provided insights into the ways Ruby and Rails allow us to navigate various methods and classes. Thank you all for being a part of this session!
00:20:43.920
If you have questions or wish to dive deeper, I will be hanging out here. Thank you once more!
00:20:57.400
As I wrap things up, if you're interested in similar topics, feel free to reach out or check my resources, including links to various Ruby materials.