David Harkness

Apr 12, 2015 15:32
Not necessarily. I'm talking about refactoring the Mappings class which wouldn't need an interface, but you were speaking about ClientData, right? I'm not sure what part of the code you meant. What responsibilities do you want to refactor into separate classes? Start by listing those, and some appropriate class names will pop out at you.
Apr 12, 2015 04:39
Any time you see fields with similar names like primaryHostIdToPartitionMapping and secondaryHostIdToPartitionMapping it's a clue to a refactoring. Both mappings require hostIdToMachineMapping which could be shared easily between two mapping class instances. That's an example of what I mentioned earlier.
Apr 12, 2015 04:36
There's no reason they couldn't share an instance to manage the block list and others to manage the host-to-IP mappings
Apr 12, 2015 04:35
@lining That sounds similar to what I was thinking from your description, though I would say two instances of the same class (maybe what you meant).
Apr 11, 2015 21:46
you're welcome. good luck!
Apr 11, 2015 21:37
ok I'll be in and out today but I'll keep the window open. that was a fun exercise :)
Apr 11, 2015 21:36
cool
Apr 11, 2015 21:35
starting to look like JavaScript :p
Apr 11, 2015 21:32
added signaling ultimate failure when you run out of hosts or all fail
Apr 11, 2015 21:30
ok, got it
Apr 11, 2015 21:23
the problem is that the callback needs to continue/break, but you don't want to duplicate the code. lemme think a min on it...
Apr 11, 2015 21:23
it's complicated and still needs to handle the looping correctly. i.e. it's not done.
Apr 11, 2015 21:22
ok I updated it
Apr 11, 2015 21:18
problem is that then the requests needs to block on the future, requiring a new thread. It could use an anonymous class as the callback inside execute.
Apr 11, 2015 21:17
right now the callback sets the final result on the SettableFuture when successful. oh, hmm, inversion of control here. Ideally you'd set a future for success failure on the request's future--not the final future. then the request would break/continue depending on success/failure...
Apr 11, 2015 21:16
filled in a little more
Apr 11, 2015 21:10
the failover is a little tricky. probably need to move the success/failure into the new DataRequest class with its own future.
Apr 11, 2015 21:02
sure, gimme a min
Apr 11, 2015 21:02
so DataClient only uses the key and ip mappings to build a list of hosts and create a DataFetchRequest.
Apr 11, 2015 21:01
a DataFetchRequest
Apr 11, 2015 21:01
or encapsulate the hosts and other necessary data into a new class that gets created by getData() and is responsible for executing the calls to the server and failover.
Apr 11, 2015 20:59
so ideally you would refactor that part of the code from getData() and have onFailure() call into it
Apr 11, 2015 20:58
yeah, you answered as I asked
Apr 11, 2015 20:58
haha, jinx
Apr 11, 2015 20:58
I see you're passing the remaining IPs to the callable, I assume for failover. Does it end up doing the same logic to check for blocked hosts?
Apr 11, 2015 20:56
This avoids the iterator entirely
Apr 11, 2015 20:55
while (!listOfHostnames.isEmpty()) {
    String hostname = listOfHostNames.remove();
    if (!ClientUtils.isEmpty(hostname) && !ClientData.isBlockHost(hostname)) {
        executeForServers(responseFuture, key, firstHostname, listOfHostnames);
    }
    isFound = true;
    break;
}
Apr 11, 2015 20:54
oh you mean because you're modifying the list while iterating? possibly, tho the iterator may be smart enough to avoid it. You could change the code to avoid it for sure:
Apr 11, 2015 20:52
And that could be made simpler by giving the list of blocked hosts to the class that maps host names to IP addresses to return null for any blocked host straight away
Apr 11, 2015 20:52
You could move the logic for checking the blocklist into the code that produces the list of hostnames, omitting any host that is already blocked
Apr 11, 2015 20:49
lemme check
Apr 11, 2015 20:48
Cool. I built that backend two years ago and haven't had to touch it since. No wait, three years? wow
Apr 11, 2015 20:47
I haven't used AsyncRestTemplate yet (Spring 4.0?), but it looks handy. I have a backend service that uses futures for the results but threads for the REST calls that produce their results. It would be better to have it all be futures.
Apr 11, 2015 20:45
Okay, the logic looks clear enough. I'd definitely refactor the longer methods into shorter ones which will help point out where you could extract logic into classes. But it works so... :)
Apr 11, 2015 20:40
ok reading that...
Apr 11, 2015 20:34
Q: You look up pri/sec loc/rem hostnames every time. Do you use all four IPs every time or only some of them based on the values in the DataKey?
Apr 11, 2015 20:32
Another principle: "Tell, Don't Ask".
Apr 11, 2015 20:31
Better still frank.driveCarIfBlue()
Apr 11, 2015 20:31
Better to do if (frank.hasBlueCar()) { ... } :)
Apr 11, 2015 20:30
It's like this:
if (bob.isCarBlue(frank.getCar()) { frank.getCar().drive(); }
Apr 11, 2015 20:30
Asking a different class ClientUtils to inspect mappings from another class is dodgy.
Apr 11, 2015 20:29
Yes
Apr 11, 2015 20:29
It may not seem like much now because of all those helper methods. If you refactor the maps into classes it becomes cleaner.
Apr 11, 2015 20:28
public boolean hasPrimaryHostMappings() { return !primaryHostIdToPartitionMapping.isEmpty(); }
Apr 11, 2015 20:27
and in Mappings class:
Apr 11, 2015 20:27
if (mappings.hasPrimaryHostMappings()) {...}
Apr 11, 2015 20:26
ok let's hit that first.
Apr 11, 2015 20:26
Can you show me the code that uses those four IP addresses? I suspect if you were to encapsulate the maps you could simplify that logic.
Apr 11, 2015 20:25
ok