Skip to content
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

Make ImageCache init private #665

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from

Conversation

andrewdmontgomery
Copy link
Contributor

Closes #388

Description

This PR makes the ImageCache init private. Since TestImageCache was using an ImageCache as its storage, I refactored it to use a dictionary.

And since it now has its own caching logic, I thought it would be good to unit-test it.

Testing Steps

  • Code review
  • CI should be 🟢

@andrewdmontgomery andrewdmontgomery force-pushed the andrewdmontgomery/ImageCache-private-init branch from 250ed3a to 4bb042b Compare February 11, 2025 19:25
@wpmobilebot
Copy link

wpmobilebot commented Feb 11, 2025

Gravatar Prototype Build📲 You can test the changes from this Pull Request in Gravatar Prototype Build by scanning the QR code below to install the corresponding build.
App NameGravatar Prototype Build Gravatar Prototype Build
Build Number2123
Version1.0
Bundle IDcom.automattic.gravatar-sdk-demo-uikit.prototype-build
Commit8424b6d
App Center BuildGravatar SDK Demo - UIKit #606
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@andrewdmontgomery andrewdmontgomery force-pushed the andrewdmontgomery/ImageCache-private-init branch from 4bb042b to ef1f120 Compare February 11, 2025 19:52
@@ -2,50 +2,60 @@ import Gravatar
import UIKit

package final class TestImageCache: ImageCaching, @unchecked Sendable {
let imageCache = ImageCache()
private var cache: [String: CacheEntry] = [:]
Copy link
Contributor Author

@andrewdmontgomery andrewdmontgomery Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using a Dictionary instead of the ImageCache.shared instance, we avoid having to make a bunch of private types package:

  • private class NSCacheForImage
  • private final class CacheEntryObject
  • NSCache extension fileprivate subscript(_ key): String) -> CacheEntry?


package typealias CacheMessage = (operation: CacheMessageType, key: String)
typealias CacheMessage = (operation: CacheMessageType, key: String?)
Copy link
Contributor Author

@andrewdmontgomery andrewdmontgomery Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compiles with internal access.

More importantly, I made key optional because there is no key used when clearing the cache.

@@ -19,6 +19,9 @@ public protocol ImageCaching: Sendable {
/// `.inProgress(task)` is used by the image downloader to check if there's already an ongoing download task for the same image. If yes, the image
/// downloader awaits that ask instead of starting a new one.
func getEntry(with key: String) -> CacheEntry?

/// Clears all entries from the cache
func clear()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIU this is just added for the unit tests. We want to test the default implementation there which is the ImageCache struct. So I think we don't need to add a new method to the protocol just for unit testing purpose. 🤔

We can cast the shared instance to ImageCache and add clear() only to ImageCache.

Like:

 let cache = try XCTUnwrap(ImageCache.shared as? ImageCache)
 cache.clear()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah shoot, I had meant to add a comment about this.

Yes, true, we only need it for testing in this PR. But I wondered if we wanted to make it clearable, generally. I know it's an in-memory cache. But are there times when we (or developers) might legitimately want to clear the cache without quitting the app?

I was thinking it would be handy during development.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool why not...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, I talked too soon. Adding a new protocol method is a breaking change. So it would require a major release and we wouldn't want that just for this.

during development

During development is easy, ImageCache is a public struct, one can typecast the shared instance to it and call clear() that way.

Copy link
Contributor Author

@andrewdmontgomery andrewdmontgomery Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a new protocol method is a breaking change. So it would require a major release and we wouldn't want that just for this.

That's a good point. Since it would be adding functionality (not breaking existing functionality), it would require a MINOR release.

I just removed that. But then it occurred to me, that the main purpose of this PR is to remove functionality. That breaks existing functionality. That requires a MAJOR release.

I think this PR should not target trunk. It should target our next major release.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh good point. I don't know why but I assumed the init() was was just internal. Yeah we can freeze this PR for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. Since it would be adding functionality (not breaking existing functionality), it would require a MINOR release.

Having said that, adding things to a "protocol" is not a new functionality I think, It's "demanding" new functionality. Like for example, Jetpack has its own image cache that implements this protocol. After this change it would generate a build error because Jetpack misses the implementation for this new method.

@andrewdmontgomery andrewdmontgomery force-pushed the andrewdmontgomery/ImageCache-private-init branch from ef1f120 to 4b8065c Compare February 18, 2025 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make "ImageCache" init private
3 participants