Stephen A. Davis
webdavis.bsky.social
Stephen A. Davis
@webdavis.bsky.social
Hi, I’m Stephen 👋. I like to talk about software architecture and test-driven development 🧪

Check out my work on https://github.com/webdavis/webdavis
How are you liking it so far? (That’s the resource I am considering for getting started with SwiftUI)
February 16, 2025 at 12:11 AM
Dope! Any hot takes from the lesson?
February 9, 2025 at 6:43 PM
This took me forever to wrap my head around and it all boiled down to my lack of understanding of the Swift language.

The more you know!
January 28, 2025 at 1:50 AM
Now here's an enum *without* associated value types.

Since there are no associated value types the compiler says we can compare instances of this Error type and slaps on the Equatable protocol at compile time.
January 28, 2025 at 1:50 AM
As it turns out, in Swift, enums with no associated values get free Equatable synthesis!

Here is an enum *with* associated value types:
January 28, 2025 at 1:50 AM
So what the heck was going on?

Somehow, the compiler is saying that RemoteFeedLoader.Error conforms to Equatable.

This led me to believe that the compiler was auto-synthesizing RemoteFeedLoader.Error's conformance to Equatable.

But what conditions need to be met in order for that to happen?
January 28, 2025 at 1:50 AM
We could explicitly conform RemoteFeedLoader.Error to Equatable like so, but apparently we don't need to? 🤔
January 28, 2025 at 1:50 AM
Here's the FeedLoader protocol's implementation class, RemoteFeedLoader.

No where in this code did we explicitly conform the Error type to Equatable:
January 28, 2025 at 1:50 AM
On the surface it makes sense: LoadFeedResult is Equatable if the Error in the failure case is Equatable.

This means that the protocol's associatedtype Error need to conform to Equatable, which means that whatever class implements the protocol need to have an Equatable Error type.
January 28, 2025 at 1:50 AM
If we uncomment the conditional conformance (the commented out line above), then the compiler error goes away 🫰, and we can compare LoadFeedResult types using XCTAssertEqual.
January 28, 2025 at 1:50 AM
The puzzle 🧩:

Whenever I commented out the following line in the interface boundary, I would then get the accompanying compile-time error in the test code:
January 28, 2025 at 1:50 AM
No worries haha, still fun 👏
January 25, 2025 at 2:39 AM
This is really interesting and reminds me how developers go from user stories to use cases. Seems every domain has its techniques for dialing in. Great stuff!
January 25, 2025 at 2:38 AM
😆 I won’t be passing any Ophthalmology tests, but I enjoyed the UI! Great work!
January 21, 2025 at 4:30 PM
1. What testing framework I should use.

2. If it’s is a class-per-test framework (e.g. the JUnit approach) or not.

3. If the language supports interfaces/protocols. If not, then what does it use to achieve composition?
January 19, 2025 at 11:04 PM
This is some next level nerdom. Bravo 👏
January 17, 2025 at 6:04 AM
Argghh!

I said all this and realized that I didn't make it very clear that I am referring specifically to the "try?" syntax.

You can see it in the first code snippet as follows:

let root = try? JSONDecoder().decode(Root.self, from: data)

(I'M TIRED lol)
January 17, 2025 at 5:58 AM
Lolz 😂
January 17, 2025 at 5:54 AM
Seems kinda convoluted! Also, now we have to force unwrap root.

Maybe that's why the Swift team implemented this.

(Side note: I usually hate reading documentation, but the Swift team actually does a really good job at it.)

(7/7)
January 17, 2025 at 5:53 AM
(6/7)

Now let's see what it would be like to implement the same behavior without this syntax. We could convert this to a do-catch block, like so:
January 17, 2025 at 5:53 AM
Here is what the Apple docs say about it:

"You use try? to handle an error by converting it to an optional value. If an error is thrown while evaluating the try? expression, the value of the expression is nil."

(5/7)
January 17, 2025 at 5:53 AM
This is because Swift allows us to convert errors to optional values.

In this case we would rather throw our own domain-specific error. We don't care about the DecodingError thrown by decode().

So instead, if decode throws an error we instruct Swift to convert it to an optional value `nil`.

(4/7)
January 17, 2025 at 5:53 AM