swift – 纠结/交叉代码的方法(logging,分析等)

在处理类似分析的事情时,我通常会有一个对象,用于侦听Notification或在业务逻辑中的对象上调用方法。 这一直困扰着我,但我还没有find一个更好的模式。 例如,下面的代码分散在各处,混乱了业务逻辑。

 class SomeService { private let analytics: AnalyticsGateway func doAllTheThings() { analytics.trackStart(with: context) somethingApiClient.doSomething { error guard error = nil else { analytics.trackError(error) analytics.trackFailure("doSomething", with: context) } analytics.trackSuccess("doSomething", with: context) } do { try someOtherApiClient.doSomethingElse { [unowned self] mappedObject guard let mappedObject = mappedObject else { analytics.trackFailure("doSomethingElse", with: context) return } guard validator.validate(mappedObject) else { analytics.trackFailure("doSomethingElse", with: context) return } self.notificationCenter.post(name: SomethingElseDidUpdateNotification, object: self, userInfo: info) } } catch { analytics.trackError(error) analytics.trackFailure("doSomethingElse", with: context) } } } 

处理这类问题的方法是什么? 我喜欢收听通知/事件的方法,如果它们存在以更新整个应用程序的状态。 但是,仅为分析添加通知似乎与直接调用分析对象(尽pipe因为没有耦合而更好)相比差不多。 在整个业务逻辑中仍然存在分析特定的代码。

过去我已经用Java做了一些面向方面的编程,似乎解决了这个问题。 有没有办法做到类似的迅速? 我find了几个Objective-C AOP库,但都没有被维护。

我目前的项目使用RxSwift,我可以做一些事件( onNextonError等)…当我使用Observable s。 不过,我宁愿有一个更好的模式,可以在任何地方使用。 例:

 class SomeService { func doSomethingElse() -> Observable<SomeObject> { return Observable.create { observer in someOtherApiClient.doSomethingElse { mappedObject guard let mappedObject = mappedObject else { throw ServiceError.mappedObjectIsNil } guard validator.validate(mappedObject) else { throw ServiceError.validationFailed(mappedObject) } observer.onNext(mappedObject) observer.onCompleted() } } .instrument(for: "doSomethingElse", in: observable) } } extension Observable where E == Mappable { func instrument(for name: String, in observable: Observable<E>) -> Observable<E> { return observable.do(onError: { (error) in analytics.trackError(error) analytics.trackFailure(name, with: context) }, onCompleted: { analytics.trackSuccess(name, with: context) }, onSubscribed: { analytics.trackStart(name, with: context) }) } }