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

improve ergonomics and readability #21

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@

import Foundation

public protocol UseCase {
public protocol UseCase<Input, Output> {
associatedtype Input
associatedtype Output

func execute(input: Input) async throws -> Output
func callAsFunction(input: Input) async throws -> Output
}

extension UseCase where Input == Void {
public func callAsFunction() async throws -> Output {
try await callAsFunction(input: ())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@

import Foundation

public final class PrepareCoreDataUseCase: UseCase {
public typealias PrepareCoreDataUseCaseType = UseCase<Void, Void>

public class PrepareCoreDataUseCase: UseCase {
var prepare: () async throws -> Void

public init<R: PrepareRepository>(repository: R) {
self.prepare = repository.prepare
}

public func execute(input: Void) async {
public func callAsFunction(input: Void) async {
try? await prepare()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import Foundation

public typealias ProductUseCaseType = UseCase<Int, Product?>

public final class ProductUseCase: UseCase {

var getProduct: (_ input: Int) async throws -> Product?
Expand All @@ -17,7 +19,7 @@ public final class ProductUseCase: UseCase {
self.getProduct = repository.read(input:)
}

@Sendable public func execute(input: Int) async throws -> Product? {
public func callAsFunction(input: Int) async throws -> Product? {
return try await getProduct(input)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import Foundation

public typealias SaveProductUseCaseType = UseCase<Product, Void>

public final class SaveProductUseCase: UseCase {
var saveProduct: (_ input: Product) async throws -> Void

Expand All @@ -16,7 +18,7 @@ public final class SaveProductUseCase: UseCase {
self.saveProduct = repository.create(input:)
}

@Sendable public func execute(input: Product) async throws {
public func callAsFunction(input: Product) async throws {
return try await saveProduct(input)
}
}
37 changes: 18 additions & 19 deletions {{cookiecutter.app_name}}/Features/Sources/App/AppClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,24 @@ import Foundation
import NetworkPlatform
import PersistentPlatform

public struct AppClient {
public var prepare: (()) async -> Void
public var save: @Sendable (_ request: Domain.Product) async throws -> Void
public var product: @Sendable (_ request: Int) async throws -> Domain.Product?
}
struct AppClient {
var getProduct: any ProductUseCaseType
var saveProduct: any SaveProductUseCaseType
var prepareCoreData: any PrepareCoreDataUseCaseType

extension AppClient {
private init(
_ prepare: PrepareCoreDataUseCase, productUseCase: ProductUseCase,
saveProduct: SaveProductUseCase
init(
_ prepare: PrepareCoreDataUseCase,
getProductUseCase: ProductUseCase,
saveProductUseCase: SaveProductUseCase
) {
self.prepare = prepare.execute(input:)
self.save = saveProduct.execute(input:)
self.product = productUseCase.execute(input:)
self.prepareCoreData = prepare
self.getProduct = getProductUseCase
self.saveProduct = saveProductUseCase
}
}

extension DependencyValues {
public var appClient: AppClient {
var appClient: AppClient {
get { self[AppClient.self] }
set { self[AppClient.self] = newValue }
}
Expand All @@ -39,17 +38,17 @@ extension DependencyValues {
extension AppClient: DependencyKey {
public static var liveValue = AppClient(
PrepareCoreDataUseCase(repository: PreparePersistentRepository.live),
productUseCase: ProductUseCase(repository: RemoteProductRepository.live),
saveProduct: SaveProductUseCase(
getProductUseCase: ProductUseCase(repository: RemoteProductRepository.live),
saveProductUseCase: SaveProductUseCase(
repository: PersistentProductRepository.live))
public static var testValue = AppClient(
PrepareCoreDataUseCase(repository: PreparePersistentRepository.live),
productUseCase: ProductUseCase(repository: RemoteProductRepository.stubbed),
saveProduct: SaveProductUseCase(
getProductUseCase: ProductUseCase(repository: RemoteProductRepository.stubbed),
saveProductUseCase: SaveProductUseCase(
repository: PersistentProductRepository.live))
public static var previewValue = AppClient(
PrepareCoreDataUseCase(repository: PreparePersistentRepository.live),
productUseCase: ProductUseCase(repository: RemoteProductRepository.stubbed),
saveProduct: SaveProductUseCase(
getProductUseCase: ProductUseCase(repository: RemoteProductRepository.stubbed),
saveProductUseCase: SaveProductUseCase(
repository: PersistentProductRepository.live))
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public struct AppFeature: FeatureReducer {
switch viewAction {
case .onAppear:
return .run { send in
await appClient.prepare(Void())
try? await appClient.prepareCoreData()
await send(
.internal(
.productResponse(
Result {
try await appClient.product(1)
try await appClient.getProduct(input: 2)
})))
}
case .showSheet:
Expand All @@ -69,7 +69,7 @@ public struct AppFeature: FeatureReducer {
case .save:
return .run { [product = state.product] send in
do {
try await appClient.save(product!)
try await appClient.saveProduct(input: product!)
} catch {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
{
"identity" : "swift-composable-architecture",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-composable-architecture",
"location" : "git@github.com:pointfreeco/swift-composable-architecture.git",
"state" : {
"revision" : "cf967a28a8605629559533320d604168d733fc9c",
"version" : "1.8.0"
Expand Down
Loading