diff --git a/Library/Homebrew/dev-cmd/linkage.rb b/Library/Homebrew/dev-cmd/linkage.rb
index 0ade2bc646f0a77e14c77ced41493acc37a9e2a9..c5d43a48dc403f7127d61f277659f58c76eb4531 100644
--- a/Library/Homebrew/dev-cmd/linkage.rb
+++ b/Library/Homebrew/dev-cmd/linkage.rb
@@ -19,22 +19,22 @@ module Homebrew
   module_function
 
   def linkage
-    ARGV.kegs.each do |keg|
-      ohai "Checking #{keg.name} linkage" if ARGV.kegs.size > 1
-      database_cache = DatabaseCache.new("linkage")
-      result = LinkageChecker.new(keg, database_cache)
-      result.flush_cache_and_check_dylibs if ARGV.include?("--rebuild")
+    DatabaseCache.new(:linkage) do |database_cache|
+      ARGV.kegs.each do |keg|
+        ohai "Checking #{keg.name} linkage" if ARGV.kegs.size > 1
 
-      if ARGV.include?("--test")
-        result.display_test_output
-        Homebrew.failed = true if result.broken_dylibs?
-      elsif ARGV.include?("--reverse")
-        result.display_reverse_output
-      else
-        result.display_normal_output
-      end
+        result = LinkageChecker.new(keg, database_cache)
+        result.flush_cache_and_check_dylibs if ARGV.include?("--rebuild")
 
-      database_cache.close
+        if ARGV.include?("--test")
+          result.display_test_output
+          Homebrew.failed = true if result.broken_dylibs?
+        elsif ARGV.include?("--reverse")
+          result.display_reverse_output
+        else
+          result.display_normal_output
+        end
+      end
     end
   end
 end
diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
index 00b151b641af20df21f10bbf23c5af39be09a602..0386beb9a4ef4fd8947b63be7e33c15eb8a486dc 100644
--- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
+++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
@@ -64,10 +64,11 @@ module FormulaCellarChecks
   def check_linkage
     return unless formula.prefix.directory?
     keg = Keg.new(formula.prefix)
-    database_cache = DatabaseCache.new("linkage")
-    checker = LinkageChecker.new(keg, database_cache, formula)
-    checker.flush_cache_and_check_dylibs
-    database_cache.close
+
+    DatabaseCache.new(:linkage) do |database_cache|
+      checker = LinkageChecker.new(keg, database_cache, formula)
+      checker.flush_cache_and_check_dylibs
+    end
 
     return unless checker.broken_dylibs?
     output = <<~EOS
diff --git a/Library/Homebrew/os/mac/cache_store.rb b/Library/Homebrew/os/mac/cache_store.rb
index 49b341dcc99cdbf0aa58d00e461df6abde05dbd6..fa919d4b4c3688dc5404b871b257c6f1b649bee8 100644
--- a/Library/Homebrew/os/mac/cache_store.rb
+++ b/Library/Homebrew/os/mac/cache_store.rb
@@ -2,143 +2,97 @@ require "dbm"
 require "json"
 
 #
-# `DatabaseCache` is a class acting as an interface to a persistent storage
-# mechanism residing in the `HOMEBREW_CACHE`
+# `DatabaseCache` acts as an interface to a persistent storage mechanism
+# residing in the `HOMEBREW_CACHE`
 #
 class DatabaseCache
-  # Name of the database cache file located at <HOMEBREW_CACHE>/<name>.db
-  #
-  # @return [String]
-  attr_accessor :name
+  # Users have read and write, but not execute permissions
+  DATABASE_MODE = 0666
 
-  # Instantiates new `DatabaseCache` object
+  # Opens and yields a database in read/write mode
   #
-  # @param  [String] name
-  # @return [nil]
+  # DBM::WRCREAT: Creates the database if it does not already exist
   def initialize(name)
-    @name = name
-  end
-
-  # Memoized `DBM` database object with on-disk database located in the
-  # `HOMEBREW_CACHE`
-  #
-  # @return [DBM] db
-  def db
-    @db ||= DBM.open("#{HOMEBREW_CACHE}/#{name}", 0666, DBM::WRCREAT)
-  end
-
-  # Close the `DBM` database object after usage
-  #
-  # @return [nil]
-  def close
-    db.close
+    @db = DBM.open("#{HOMEBREW_CACHE}/#{name}.db", DATABASE_MODE, DBM::WRCREAT)
+    yield(@db)
+    @db.close
   end
 end
 
 #
-# `CacheStore` is an abstract base class which provides methods to mutate and
-# fetch data from a persistent storage mechanism
-#
-# @abstract
+# `CacheStore` provides methods to mutate and fetch data from a persistent
+# storage mechanism
 #
 class CacheStore
-  # Instantiates a new `CacheStore` class
-  #
-  # @param  [DatabaseCache] database_cache
-  # @return [nil]
   def initialize(database_cache)
-    @db = database_cache.db
+    @database_cache = database_cache
   end
 
   # Inserts new values or updates existing cached values to persistent storage
   # mechanism
-  #
-  # @abstract
-  # @param  [Any]
-  # @return [nil]
   def update!(*)
     raise NotImplementedError
   end
 
   # Fetches cached values in persistent storage according to the type of data
   # stored
-  #
-  # @abstract
-  # @param  [Any]
-  # @return [Any]
-  def fetch(*)
+  def fetch_type(*)
     raise NotImplementedError
   end
 
   # Deletes data from the cache based on a condition defined in a concrete class
-  #
-  # @abstract
-  # @return [nil]
   def flush_cache!
     raise NotImplementedError
   end
 
   protected
 
-  # A class instance providing access to the `DBM` database object
+  attr_reader :database_cache
+
+  # Parses `DBM` stored `String` into ruby `Hash`
   #
-  # @return [DBM]
-  attr_reader :db
+  # DBM stores ruby objects as a ruby `String`. Hence, when fetching the data,
+  # to convert the ruby string back into a ruby `Hash`, the string is converted
+  # into a JSON compatible string, where it may be parsed by the JSON.parse
+  # function
+  def string_to_hash(string)
+    JSON.parse(string.gsub("=>", ":"))
+  end
 end
 
 #
-# `LinkageStore` is a concrete class providing methods to fetch and mutate
-# linkage-specific data used by the `brew linkage` command
-#
-# If the cache hasn't changed, don't do extra processing in `LinkageChecker`.
-# Instead, just fetch the data stored in the cache
+# `LinkageStore` provides methods to fetch and mutate linkage-specific data used
+# by the `brew linkage` command
 #
 class LinkageStore < CacheStore
-  # Types of dylibs of the form (label -> array)
-  HASH_LINKAGE_TYPES = %w[brewed_dylibs reverse_links].freeze
-
-  # The keg name for the `LinkageChecker` class
-  #
-  # @return [String]
-  attr_reader :key
+  HASH_LINKAGE_TYPES = [:brewed_dylibs, :reverse_links].freeze
 
-  # Initializes new `LinkageStore` class
-  #
-  # @param  [String]        keg_name
-  # @param  [DatabaseCache] database_cache
-  # @return [nil]
   def initialize(keg_name, database_cache)
-    @key = keg_name
+    @keg_name = keg_name
     super(database_cache)
   end
 
-  # Inserts new values or updates existing cached values to persistent storage
-  # mechanism according to the type of data
-  #
-  # @param  [Hash] path_values
-  # @param  [Hash] hash_values
-  # @return [nil]
   def update!(
     path_values: {
-      "system_dylibs" => %w[], "variable_dylibs" => %w[], "broken_dylibs" => %w[],
-      "indirect_deps" => %w[], "undeclared_deps" => %w[], "unnecessary_deps" => %w[]
+      system_dylibs: %w[],
+      variable_dylibs: %w[],
+      broken_dylibs: %w[],
+      indirect_deps: %w[],
+      undeclared_deps:  %w[],
+      unnecessary_deps: %w[],
     },
     hash_values: {
-      "brewed_dylibs" => {}, "reverse_links" => {}
+      brewed_dylibs: {},
+      reverse_links: {},
     }
   )
-    db[key] = {
+    database_cache[keg_name] = {
       "path_values" => format_path_values(path_values),
       "hash_values" => format_hash_values(hash_values),
     }
   end
 
-  # Fetches cached values in persistent storage according to the type of data
-  # stored
-  #
-  # @param  [String] type
-  # @return [Any]
-  def fetch(type:)
+  def fetch_type(type)
     if HASH_LINKAGE_TYPES.include?(type)
       fetch_hash_values(type: type)
     else
@@ -146,60 +100,36 @@ class LinkageStore < CacheStore
     end
   end
 
-  # A condition for where to flush the cache
-  #
-  # @return [String]
   def flush_cache!
-    db.delete(key)
+    database_cache.delete(keg_name)
   end
 
   private
 
-  # Fetches a subset of paths where the name = `key`
-  #
-  # @param  [String] type
-  # @return [Array[String]]
+  attr_reader :keg_name
+
   def fetch_path_values(type:)
-    return [] unless db.key?(key) && !db[key].nil?
-    string_to_hash(db[key])["path_values"][type]
+    return [] if !database_cache.key?(keg_name) || database_cache[keg_name].nil?
+    string_to_hash(database_cache[keg_name])["path_values"][type.to_s]
   end
 
-  # Fetches a subset of paths and labels where the name = `key`. Formats said
-  # paths/labels into `key => [value]` syntax expected by `LinkageChecker`
-  #
-  # @param  [String] type
-  # @return [Hash]
   def fetch_hash_values(type:)
-    return {} unless db.key?(key) && !db[key].nil?
-    string_to_hash(db[key])["hash_values"][type]
-  end
-
-  # Parses `DBM` stored `String` into ruby `Hash`
-  #
-  # @param [String] string
-  # @return [Hash]
-  def string_to_hash(string)
-    JSON.parse(string.gsub("=>", ":"))
+    return {} if !database_cache.key?(keg_name) || database_cache[keg_name].nil?
+    string_to_hash(database_cache[keg_name])["hash_values"][type.to_s]
   end
 
   # Formats the linkage data for `path_values` into a kind which can be parsed
-  # by the `string_to_hash` method. Converts ruby `Set`s to `Array`s.
-  #
-  # @param  [Hash(String, Set(String))] hash
-  # @return [Hash(String, Array(String))]
+  # by the `string_to_hash` method. Converts ruby `Set`s to `Array`s
   def format_path_values(hash)
-    hash.each_with_object({}) { |(k, v), h| h[k] = v.to_a }
+    hash.each_with_object({}) { |(k, v), h| h[k.to_s] = v.to_a }
   end
 
   # Formats the linkage data for `hash_values` into a kind which can be parsed
   # by the `string_to_hash` method. Converts ruby `Set`s to `Array`s, and
   # converts ruby `Pathname`s to `String`s
-  #
-  # @param  [Hash(String, Set(Pathname))] hash
-  # @return [Hash(String, Array(String))]
   def format_hash_values(hash)
     hash.each_with_object({}) do |(outer_key, outer_values), outer_hash|
-      outer_hash[outer_key] = outer_values.each_with_object({}) do |(k, v), h|
+      outer_hash[outer_key.to_s] = outer_values.each_with_object({}) do |(k, v), h|
         h[k] = v.to_a.map(&:to_s)
       end
     end
diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb
index c123d72905d4fe0027732217d62bd773e454b1e9..650cea0e9f40ff0408ca3c35ee578e19d8b0555e 100644
--- a/Library/Homebrew/os/mac/linkage_checker.rb
+++ b/Library/Homebrew/os/mac/linkage_checker.rb
@@ -15,37 +15,37 @@ class LinkageChecker
   # 'Hash-type' cache values
 
   def brewed_dylibs
-    @brewed_dylibs ||= store.fetch(type: "brewed_dylibs")
+    @brewed_dylibs ||= store.fetch_type(:brewed_dylibs)
   end
 
   def reverse_links
-    @reverse_links ||= store.fetch(type: "reverse_links")
+    @reverse_links ||= store.fetch_type(:reverse_links)
   end
 
   # 'Path-type' cached values
 
   def system_dylibs
-    @system_dylibs ||= store.fetch(type: "system_dylibs")
+    @system_dylibs ||= store.fetch_type(:system_dylibs)
   end
 
   def broken_dylibs
-    @broken_dylibs ||= store.fetch(type: "broken_dylibs")
+    @broken_dylibs ||= store.fetch_type(:broken_dylibs)
   end
 
   def variable_dylibs
-    @variable_dylibs ||= store.fetch(type: "variable_dylibs")
+    @variable_dylibs ||= store.fetch_type(:variable_dylibs)
   end
 
   def undeclared_deps
-    @undeclared_deps ||= store.fetch(type: "undeclared_deps")
+    @undeclared_deps ||= store.fetch_type(:undeclared_deps)
   end
 
   def indirect_deps
-    @indirect_deps ||= store.fetch(type: "indirect_deps")
+    @indirect_deps ||= store.fetch_type(:indirect_deps)
   end
 
   def unnecessary_deps
-    @unnecessary_deps ||= store.fetch(type: "unnecessary_deps")
+    @unnecessary_deps ||= store.fetch_type(:unnecessary_deps)
   end
 
   def flush_cache_and_check_dylibs
@@ -207,8 +207,6 @@ class LinkageChecker
   end
 
   # Helper function to reset dylib values when building cache
-  #
-  # @return [nil]
   def reset_dylibs!
     store.flush_cache!
     @system_dylibs    = Set.new
@@ -222,21 +220,19 @@ class LinkageChecker
   end
 
   # Updates data store with package path values
-  #
-  # @return [nil]
   def store_dylibs!
     store.update!(
       path_values: {
-        "system_dylibs"    => @system_dylibs,
-        "variable_dylibs"  => @variable_dylibs,
-        "broken_dylibs"    => @broken_dylibs,
-        "indirect_deps"    => @indirect_deps,
-        "undeclared_deps"  => @undeclared_deps,
-        "unnecessary_deps" => @unnecessary_deps,
+        system_dylibs: @system_dylibs,
+        variable_dylibs: @variable_dylibs,
+        broken_dylibs: @broken_dylibs,
+        indirect_deps: @indirect_deps,
+        undeclared_deps: @undeclared_deps,
+        unnecessary_deps: @unnecessary_deps,
       },
       hash_values: {
-        "brewed_dylibs"    => @brewed_dylibs,
-        "reverse_links"    => @reverse_links,
+        brewed_dylibs: @brewed_dylibs,
+        reverse_links: @reverse_links,
       },
     )
   end