Syntax to store results of previous mapping - project-reactor

I would like to know the good way to use results of previous mapping in spring web-flux, for example
Mono.just(request)
...
.flatMap(object0 -> createObject1(object0))
.flatMap(object1 -> createObject2(object1))
...
what a good way to get object0 at this point, so we could add something like
.flatmap(object0 -> createResult(object0))
I solved it by uniting this both method so that we have object0 in global variable, but it doesn't looks good.
Another example
Mono.just(request)
...
.flatMap(object0 -> createResponse(object))
.map(result -> mapToObject1(result))
.flatMap(object1-> saveObject1(object1))
How to return "result" at this point?
Could you please give link to good example of same cases, because solution to unite this line to make result global doesn't looks good as it creates ambiguous methods?

You can wrap several objects into a reactor.util.function.Tuples, like this:
Mono.just(request)
...
.flatMap(object0 -> Tuples.of(object0, createObject1(object0)))
.flatMap(tuple -> createObject2(tuple.getT2()))
...
I don't know if it's really a best practice here, because your code snippet is very generic and I can't say whether it's an issue with the underlying API.

For the first case, because you are using flatMap for createObject1(object0), I assume that it is returning Mono<Object1> , I think the following code snippet can do what you wanted.
public Mono<Class1> createObject1(Class0 object0) {
//...
}
public Mono<Class2> createObject2(Class1 object1, Class0 object0) {
//...
}
public void test() {
Mono.just(new Class0())
.flatMap(object0 -> createObject1(object0).zipWith(Mono.just(object0)))
.flatMap(tuple -> createObject2(tuple.getT1(), tuple.getT2()));
}
For the second case, as the accepted answer suggested, using reactor.util.function.Tuples in map will do.

My version looks like that
.flatMap(upperResult -> {
return Mono.just(upperResult).zipWith(monoGeneratingFunction(upperResult));
})
.flatMap(tuple -> {
var upperResult = tuple.getT1();
var lowerResult = tuple.getT2();
})

You can use zipWhen with straight on the mono. zipWhen is a specific operator that combines results.
Mono.just(request)
...
.zipWhen(object0 -> createObject1(object0))
...

Related

Testing dependency injection

I am using Dependency Inversion the functional way (ie. using closure instead of protocol/interface/pure virtual) like so:
class StatusPoller {
init(api: #escaping (String, String) -> Observable<Data>,
getAccessToken: #escaping () -> String) {
...
}
}
class HeartbeatSender {
init(api: #escaping (String, String) -> Observable<Data>,
getAccessToken: #escaping () -> String) {
...
}
}
class Api {
func pollStatus(id: String, accessToken: String) -> Observable<Data> {
...
}
func sendHeartbeat(id: String, accessToken: String) -> Observable<Data> {
...
}
}
Now this is the problem. In the dependency injection resolver (Swinject), it goes like this:
container.register(StatusPoller.self) { _ in
let api = SwinjectApi.container.resolve(Api.self)!
let authStore = SwinjectAuth.container.resolve(AuthStore.self)!
return StatusPoller(api: api.pollStatus(id:accessToken:),
getAccessToken: authStore.getAccessToken)
}
container.register(HeartbeatSender.self) { _ in
let api = SwinjectApi.container.resolve(Api.self)!
let authStore = SwinjectAuth.container.resolve(AuthStore.self)!
return StatusPoller(api: api.pollStatus(id:accessToken:),
getAccessToken: authStore.getAccessToken)
}
I accidentally used the same dependency for the API member of different classes. It, fortunately (or unfortunately depending on your POV), worked fine for almost a year now since the backend doesn't really check for the heartbeat consistency (or at all). However, there's a new feature in the last few months that required the checking of the heartbeat of the client all the time now and this caused a bug. I've fixed it after I noticed that the heartbeat is not actually being sent at all because of that mistake above.
So my question is: How do I prevent that in the future? Testing the dependency injection? But, how though? I still don't get how I can make sure that I have injected the correct dependency.
Thanks
EDIT:
To make the question more clear, it's basically the equivalent of this but in functional:
Suppose I have an interface like this:
protocol VoipHandlerInterface {
...
}
class TwilioVoipHandlerAdapter: VoipHandlerInterface {
...
}
class AsteriskVoipHandlerAdapter: VoipHandlerInterface {
...
}
class VoipManagerInteractor {
let voipHandler: VoipHandlerInterface
init(voipHandler: VoipHandlerInterface) {
self.voipHandler = voipHandler
}
}
How do I test / make sure that, for instance, I use Twilio instead of Asterisk in VoipManagerInteractor?
That's the problem with dependency injection. Your unit tests can check if the dependency is used correctly but they can't check to ensure that the correct dependency is passed in. Only integration tests can do that.
The best you can do here is create a UI Testing Bundle for your app and check some minimal functionality to ensure that the correct dependency is passed in. Try to minimize the number of integration tests you need though because they are brittle and slow.
Lastly, instead of dependency injection, attempt dependency rejection. Make your boundaries value types instead of interfaces.

Swift: How to deal with method overloads where only the return type differs and the result is discardable?

this is my first question and I hope you guys can help me out.
Lets assume I've written a Framework in Swift that does stuff purely with native Swift Types. This is our interface:
class Foo {
#discardableResult
public func perform(query: String) -> [String: Any]? {
return [:]
}
}
Note that our result is discardable.
I would now like to support other Libraries optionally. I know we have Codable and stuff but lets assume that I want to support SwiftyJSON optionally by creating an extension that only compiles when SwiftyJSON can be imported.
#if canImport(SwiftyJSON)
import SwiftyJSON
extension Foo {
#discardableResult
func perform(query: String) -> JSON? {
// Call internal func => cast JSON => return JSON
return JSON()
}
}
#endif
Without SwiftyJSON (can not import) this compiles:
let bar = Foo().perform(query: "")
With SwiftyJSON it does not because its ambiguous.
Return type has to be explicitly defined like:
let baz: [String: Any]? = Foo().perform(query: "")
// or
let bar: JSON? = Foo().perform(query: "")
For calls where I want the result thats fine.
BUT: Since we have a discardableResult calls like
Foo().perform(query: "")
will always be ambiguous.
The following calls work but are not very nice imho.
Foo().perform(query: "") as JSON?
Foo().perform(query: "") as [String: Any]?
What is the best way to deal with this problem? Should the method just not be overloaded and have a different name instead? Or am I overlooking something that makes the calls non ambiguous in a nice way?
Edit:
A comment suggested to remove discardableResult. I really do not wanna do that since that would lead to a lot of calls that look like this:
_ = Foo().perform(query: "")
The more I think about the problem it occurs to me that there might just not be a good solution for this..
Actually, removing #discardableResult wouldn't work, and _ = Foo().perform(query: "") wouldn't compile, it would still have the same ambiguity: it's not that the compiler is being nitpicky, but it has literally no way of knowing which of your two functions to call!
It might be interesting to think about what behavior you'd expect from this line, and why.
You seem to want to have a function based on an existing function which:
Returns a different type;
Has the same name and parameters;
Has a discardable result.
Unfortunately, it looks like it's a classic "pick any two" type of scenario…
Well, let's do just that! Let's see what happens if we stop insisting on any one of the three conditions.
Let me use a simpler example:
#discardableResult func doSomething() -> String {
return "a"
}
#discardableResult func doSomething() -> Int {
return 1
}
doSomething() // won't compile
let x:String
x = doSomething() // "a"
We have a function overloaded with two return types (String and Int), and we see that we cannot discard its result as it would result in unresolvable ambiguity.
1. Single return type: use an enum with a payload
Let's eliminate the first condition, and try using a single return type. This is possible:
enum ReturnType {
case text(_ payload:String)
case number(_ payload:Int)
}
#discardableResult func doSomething() -> ReturnType {
if ... // some condition
{
return .text("a")
} else {
return .number(1)
}
}
doSomething() // works
let x = doSomething() // ReturnType.text("a") or ReturnType.number(1)
Here we cannot (easily) extend the functionality via extensions; rather, we'd need to touch the enum and function code with all the possible options every time we want to add a new return type. (Of course advanced APIs can also be created that help third parties easily write extensions… If it's worth the effort.)
We would also need a way to determine which return type to choose: it can be a function parameter, or a value stored elsewhere, etc. Here's an example with a parameter:
#discardableResult func doSomething(useText:Bool = false) -> ReturnType {
if useText {
return .text("a")
} else {
return .number(1)
}
}
doSomething() // works
doSomething(useText:true) // works
let x = doSomething() // ReturnType.number(1)
let x2 = doSomething(useText:false) // ReturnType.number(1)
let x3 = doSomething(useText:true) // ReturnType.text("a")
Note: Here, we lose the convenience of having the compiler infer the type from the call site; since the type is now an opaque wrapper, it's no longer the compiler's business to make sure that the wrapped type is correct. This may be a high cost for simply maintaining "result discardability," but then it may also allow us to abstract away some details, only unwrapping the "payload" when needed, which can have its own benefits.
2. Change the name or parameters of the function
This is quite easy:
#discardableResult func doSomething() -> String {
return "a"
}
#discardableResult func doSomethingElse() -> Int {
return 1
}
doSomething() // works
doSomethingElse() // works
let x = doSomething() // "a"
let y = doSomethingElse() // 1
We can also use this in an extension. All we lose is the shared name.
Changing the parameters is also possible but it would be pretty silly in this already-silly example:
#discardableResult func doSomething() -> String {
return "a"
}
#discardableResult func doSomething(thinkOfAnyNumber:Int) -> Int {
return 1
}
doSomething() // "a"
doSomething(thinkOfAnyNumber:42) // 1
Note: I'd obviously only do this if the additional parameters actually make sense.
Note 2: The parameter configuration is different between the two functions, not the parameter values like in the previous case.
3. Do not make the result discardable
Note that simply removing the #discardableResult attribute won't make it impossible to try to discard the result: you'll still be able to try the _ = assignment, or simply ignore the function result (and the compiler warning). Both will ultimately fail to compile, so it will be up to the user of the API to avoid doing either.
Hopefully, your function does some other things (side effects) than provide a return value: in that case, there may be little use in discarding the result of a function that does nothing but provide that result, and one may probably be better off not calling it in the first place.
If the side effects are identical between the two overloaded functions, you can factor them out into a single function:
func doTheActualWork() {
// ...
}
func doSomething() -> String {
doTheActualWork()
return "a"
}
func doSomething() -> Int {
doTheActualWork()
return 1
}
doSomething() // won't compile
doTheActualWork() // use this instead
let z:String = doSomething() // "a"
Note that this can also be done via extensions as long as they re-use existing functions and only overload them with different signatures and/or return types.
Now if the side effects (i.e. doTheActualWork() implementations) are also different in the two cases… Then I give up. But that can be handled as well.
Well, this is what I've been able to gather on this interesting problem. Now I may be dead wrong, and there may be something better out there… We'll find out soon enough.

How to return closure in the generic

Now I using Realm to create a singleton, but I faced a problem, if I want to return a closure in the generic, and there are different types (Ex:.Case type return [Case], .Product type return [Product]), but I have no idea to implement this fuction.
Could anyone help me with this problem?Thanks!
DataType:
enum DataType{
case Case
case Product
case Category
case Composition
}
fetchItem fuction:
func fetchItem<T>(type: DataType,complete:#escaping ([T]) -> ()) {
var list:[T]? = []
switch type {
case .Case:
let realm = try! Realm()
let caseResult = realm.objects(Case.self)
caseResult.forEach { (item) in
...
}
complete([])
return
case .Product:
return
case .Category:
return
case .Composition:
return
}
}
Templating a function is the class that you want to get.
Let's take for exemple this function
func showTemplate<T>(myVariable: T) {
print(myVariable)
}
Here, if I want to call the showTemplate function I must do it with the type I want :
showTemplate<String>() # print a string
showTemplate<Int>() # print a int
showTemplate<myClass> # print a myClass
So you are having a problem, but in the wrong way because with templating, you HAVE to know the class before you call the function.
You can for example try to use inheritance and templating your motherClass with your wanted class.
class wantedClass {
var myCaseVariable: Case
var myProductVariable: Product
var myThingsVariable: Things
init() {
}
fillClass<T: Case>() {
// set case
}
// Etc etc
}
Moreover, I don't think that templating is the good solution here, I suggest to look at this : Using a Type Variable in a Generic
I believe you cannot do this for completely different types in one place using only generic type (not any class-holders or so). Maybe you should create separate funcs for each item (fetchCaseItems(), fetchProductItems, etc.). It's much clear to read and every func is responsible only for its own data type.

Factory in Swift using Generic Types

I'm trying to achieve the following in Swift - I want to pass in a type to a generic "get" function, and based on that type and the parameter, use different repositories to get back a class.
I recognize this is a bit strange to do in this way, but it would save me a lot of time and allow me to more properly refactor something later.
Here is the code but it compile errors on the Foo1Repository and Foo2Repository lines "Cannot convert the type of Foo1Repository to T".
Basically Foo1Repository should return a Foo1, which inherits from BaseEntity of course (and the same is true for Foo2)
class func Get<T: BaseEntity>(id: Int) -> T
{
if (T is Foo1) {
return Foo1Repository.Get(id)
}
else if (T == Foo2) {
return Foo2Repository.Get(id)
}
return T()
}
I was hoping to invoke this function by doing:
let foo = FactoryClass.Get<Foo1>(1)
I understand immediately you would ask "why not just call the appropriate repository, i.e."
let foo = Foo1Repository.Get(1)
and you're all set! No need for some weird factory pattern here.
Let's just say at the moment I need to try to do it above without a lot of refactoring of some code I inherited. I'll get back to planning a proper refactor later.
So I've tried a combination of things but still can't seem to get past the compiler errors. Is something like this possible, or do I need to just bite the bullet and go a different route? Thanks so much!
So I figured it out! I wanted to share the answer so others can see how to do this. Hopefully it will help.
func Get<T: BaseEntity>(id: Int) -> T
{
if (T.self == Foo1.self) {
return Foo1Repository.Get() as! T
}
else if (T.self == Foo2.self) {
return Foo2Repository.Get() as! T
}
...
return T()
}
So you can see, the whole as! T at the end was key. Also == instead of is for type checks.

How to reference a class that follows a protocol in return type of function?

I have a protocol called Social Service, declared as follows:
protocol SocialService: class {
class func testFunc()
}
A class that follows the protocol may look like this:
class Twitter: SocialService {
class func testFunc() {
}
}
I want to have a method which returns a class that follows this protocol, so calling it would look like this:
let socialService = socialServiceForServiceType(serviceType: String)
I'm not sure what I need to put as the return value type of this function. For example, this:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
doesn't give an error right here, but trying to call it as above, gives an error:
Accessing members of protocol type value 'SocialService.Type' is
unimplemented
EDIT: I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
Like the error says, this feature is unimplemented. However...
I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
If you implement a Twitter class that has no properties and that conforms to a protocol, then calling methods on that protocol will dynamically dispatch to the implementations of that instance:
protocol SocialService: class {
func testFunc()
}
class Twitter: SocialService {
func testFunc() {
println("Testing Twitter!")
}
}
func socialServiceForServiceType(serviceType: String) -> SocialService {
return Twitter()
}
let service = socialServiceForServiceType("blah")
// prints "Testing Twitter!"
service.testFunc()
If your concern is that you want to put member variables in the Twitter class, but don’t want the overhead of that for some features, then this probably suggests you want to decompose this functionality into two different classes. Alternatively, if you want a singleton instance (to handle the connectivity for example) then there are other patterns to handle this.
Use simply
func socialServiceForServiceType(serviceType: String) -> SocialService
A protocol can be the return type of a function.
Totally agree with Airspeed Velocity, but I'd like to expand on one of his points:
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
I assume you're trying to do something like this:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
...
let cls = socialServiceForServiceType("twitter")
let conn = cls.connect(user)
Or something like that. You don't need classes to achieve that. You can just return functions.
typealias Connect = User -> Connection
func connectorForServiceType(serviceType: String) -> Connect {
switch serviceType {
case "twitter": return Twitter.Connect
...
}
}
let connect = connectorForServiceType("twitter")
let conn = connect(user)
If you have a whole bundle of functions that you want to package together, just use a struct.
struct ServiceHandlers {
let connect : User -> Connection
let ping : () -> Bool
let name: () -> String
}
func standardPinger(host: String) -> () -> Bool {
return { host in
// perform an ICMP ping and return Bool
}
}
func handlersForServiceType(serviceType: String) -> ServiceHandlers {
switch serviceType {
case "twitter":
return ServiceHandlers(connect: Twitter.connect,
ping: standardPinger("www.twitter.com"),
name: { "Twitter" })
...
}
}
let service = handlersForServiceType("twitter")
let conn = service.connect(user)
In some ways this is duplicative with class methods, but (a) the features you need for class methods aren't implemented, and (b) this is much more flexible. You can return any collection of functions you want; they don't have to all be class methods. It's easier to have default behaviors (which are hard in Swift when you use inheritance). It's easier to extend because you don't necessarily have to extend all the classes (see my use of standardPinger, which is some function I've made up that returns another function; it doesn't have to be a class method).
Breaking free of class/inheritance thinking and just passing around functions can be a major benefit in Swift. Sometimes a struct is better than a protocol.
Use a Factory pattern to achieve the same.
class SocialFactory : NSObject
{
class func socialServiceForServiceType(serviceType: String) -> SocialService?
{
switch serviceType
{
case "Twitter":
return Twitter();
case "Facebook":
return Facebook()
default:
return nil;
}
}
}

Resources