Руководство по решениям для интеллектуального кэширования
TL;DR — Caches обсуждает проблемы с кэшированием, такие как связь и удобство обслуживания, и предлагает решения, такие как использование объектного посредника, тестирование сценариев аннулирования и моделирование реальных метафор кэша. В нем делается вывод, что кэши должны быть функциональными и интеллектуальными, а объекты домена не должны кэшироваться.
Проблема
- Связь
- Тестируемость
- Инвалидация кэша
- Ремонтопригодность
- Преждевременная оптимизация
- Неустойчивое поведение
- Отсутствие прозрачности
- Недетерминированное поведение
Решение
- Если у вас есть убедительный ориентир и вы готовы принять некоторую связь, поместите объект посередине.
- Модульное тестирование всех сценариев аннулирования. Опыт показывает, что мы сталкиваемся с ними постепенно.
- Найдите метафору реального кэша и смоделируйте ее.
Образец кода
Неправильный
typealias Cache<T> = MutableMap<String, List<T>> class Book( private val cachedBooks: Cache<Book> = mutableMapOf() ) { fun getBooks(title: String): List<Book> { return if (cachedBooks.containsKey(title)) { cachedBooks[title]!! } else { val booksFromDatabase = getBooksFromDatabase(title) cachedBooks[title] = booksFromDatabase booksFromDatabase } } private fun getBooksFromDatabase(title: String): List<Book> = globalDatabase().selectFrom("Books", "WHERE TITLE = $title") }
Верно
typealias Cache<T> = MutableMap<String, T> interface BookRetriever { fun bookByTitle(title: String): Book? } class Book { // Just Book-related Stuff } class DatabaseLibrarian : BookRetriever { // Go to the database (not global hopefully) override fun bookByTitle(title: String): Book? { ... } } // We always look for real-life metaphors class HotSpotLibrarian( private val inbox: Inbox, private val realRetriever: BookRetriever ) : BookRetriever { override fun bookByTitle(title: String): Book? { return if (inbox.includesTitle(title)) { // We are lucky. Someone has just returned the book copy. inbox.retrieveAndRemove(title) } else { realRetriever.bookByTitle(title) } } } class Inbox(private val books: Cache<Book> = mutableMapOf()) { fun includesTitle(title: String) { ... } fun retrieveAndRemove(title: String): Book? { ... } fun addBook(title: String, book: Book) { ... } }
Заключение
Кэши должны быть функциональными и интеллектуальными, позволяющими эффективно управлять аннулированием. Кэши общего назначения лучше всего подходят для объектов низкого уровня, таких как операционные системы, файлы и потоки, тогда как объекты домена не следует кэшировать.
Надеюсь, вам понравилось это путешествие и вы узнали что-то новое. Если вы хотите быть в курсе моих последних мыслей и идей, подпишитесь на мою информационную рассылку. Вы также можете найти меня в LinkedIn или Twitter. Давайте оставаться на связи и продолжать разговор!
Кредиты
Оригинально опубликовано на https://yonatankarp.com.
Спасибо, что дочитали до конца. Пожалуйста, подумайте о том, чтобы подписаться на автора и эту публикацию. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.