Consider using null objects to make memoization easier and remove if checks
<!--IssueSummary start-->
<details>
<summary>
Everyone can contribute. [Help move this issue forward](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#contributor-links) while earning points, leveling up and collecting rewards.
</summary>
- [Close this issue](https://contributors.gitlab.com/manage-issue?action=close&projectId=278964&issueIid=19453)
</details>
<!--IssueSummary end-->
Null objects are currently not used anywhere in GitLab (that I know of), but they can often make code a lot easier (though applying the technique retroactively is a bit tricky). Memoizing values are becomes easier. For example, instead of this:
```ruby
def latest_successful_pipeline_for_default_branch
unless defined?(@latest_successful_pipeline_for_default_branch)
@latest_successful_pipeline_for_default_branch =
pipelines.latest_successful_for(default_branch)
end
@latest_successful_pipeline_for_default_branch
end
```
One can just write:
```ruby
def latest_successful_pipeline_for_default_branch
@latest_successful_pipeline_for_default_branch ||=
pipelines.latest_successful_for(default_branch)
end
```
Null objects would also remove the need for a lot of `if` checks. For example, instead of this:
```ruby
if current_user
current_user.name
else
'Anonymous'
end
```
One could just write:
```ruby
current_user.name
```
Assuming that `NullUser` (or whatever we'd call it) were to implemnet `#name` so that it returns "Anonymous".
Another more complex example of this pattern can be seen in https://github.com/YorickPeterse/inko/tree/master/compiler (a compiler written in Ruby). Part of this code involves looking up symbols, instead of returning `nil` a `NullSymbol` is returned when no symbol could be found. This then lets you do things such as:
```ruby
self_type.lookup_type(name)
.or_else { mod.lookup_type(name) }
.type
.return_type
```
instead of something like this:
```ruby
type = self_type.lookup_type(name) || mod.lookup_type(name)
if type
type.return_type
else
nil
end
```
For the curious, the implementation of said class can be found here: https://github.com/YorickPeterse/inko/blob/74c8fdca7d8d039da71c9556a4a70c3bc316578f/compiler/lib/inkoc/symbol.rb
https://github.com/avdi/naught and https://github.com/alexpeachey/active_null look like interesting libraries to make this process easier.
cc @DouweM @rspeicher @smcgivern @dzaporozhets
issue