-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Refactor capabilities and other P2P-related stuff #2469
Refactor capabilities and other P2P-related stuff #2469
Conversation
c9a8e0e
to
d2eae71
Compare
github.com/AlDanial/cloc v 1.80 T=0.19 s (5.3 files/s, 5.3 lines/s) ------------------------------------------------------------------------------- files blank comment code ------------------------------------------------------------------------------- same 0 0 913 3405 modified 28 0 6 145 added 1 18 36 58 removed 0 9 3 103 -------------------------------------------------------------------------------
d2eae71
to
1875b88
Compare
1875b88
to
4bafea8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
In Peer the EqualsAndHashCode should include a super call. I will push that afterwards.
IntelliJ reports such issues with static code analysis (colored bg), otherwise I would not have spotted it as well ;-)
@EqualsAndHashCode(exclude = {"date"}, callSuper = true)
I tested just lightly. As that comes with many "risky" changes we have to observe well if there are any issues reported which might be connected to the topics of that PR.
@@ -39,47 +38,43 @@ | |||
@Getter | |||
@EqualsAndHashCode(exclude = {"date"}) // failedConnectionAttempts is transient and therefore excluded anyway | |||
@Slf4j | |||
public final class Peer implements NetworkPayload, PersistablePayload, SupportedCapabilitiesListener { | |||
public final class Peer extends Capabilities implements NetworkPayload, PersistablePayload, SupportedCapabilitiesListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing call to super in @EqualsAndHashCode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extension feels not really right to me here. A peer "has capabilities" and not "is capabilities".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same with SharedModel in Connection class..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aggreed. but peer.isCapabilitySupported(...)
and connection.isCapabilitySupported(...)
feels quite right. Having them implement some sort of HasCapabilities
interface would result in peer.getCapabilities().isCapabilitySupported(...)
which imho is confusing.
// TODO got even worse after refactoring | ||
List<Integer> current = Capabilities.toIntList(Capabilities.app); | ||
current.add(Capability.SEED_NODE.ordinal()); | ||
Capabilities.app.resetCapabilities(Capabilities.fromIntList(current)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not add a method for appending a capability? Check to not add duplicates can be done with capability object itself rather then ordinal, no (missing here but was at another class where it was added after checking if not already there)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
first, there is a TODO and second, we need that kind of code exactly once. and once more for the monitor.
} else { | ||
return msg instanceof CapabilityRequiringPayload && sharedModel.isCapabilitySupported(((CapabilityRequiringPayload) msg).getRequiredCapabilities()); | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The noCapabilityRequiredOrCapabilityIsSupported is very hard to understand (was worse before). Maybe we should use that refactoring moment for improving the method so it becomes more easier.
I would need more time to review the corrtectness (compared to the old version), but would prefer to invest that time in a improved method version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I thought about changing stuff around but it quickly gets dirty.
Most beautiful would be that we do not need the method at all but instead can use a connection.isCapabilitySupported(msg)
or isCapabilitySupported(msg)
directly. However, the class hierarchy has grown overly complicated over time and such a solution is not possible as things stand now (would result in a diamond pattern if Java would allow for that).
Even looks worse if depicted like that:
I even tried to use java8/9 defaults in interfaces and create some sort of mixins. Nasty stuff. Definitely needs cleanup! Small steps...
/** | ||
* The global set of capabilities, i.e. the capabilities if the local app. | ||
*/ | ||
public static final Capabilities app = new Capabilities(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a more descriptive name here. When I read Capabilities.app it was not very clear what it means.
Also does not need to be static?
Should the class extend HashSet instead of using the field capabilities - as that is basically what it holds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should make it a Guice instance scoped as singleton?
And then use it in peer and shared model as parameter passed to the constructor (I know there is missing guice and passing is painful)... So maybe keeping the Capabilities.app static is less painful?
But then maybe its better to move it to another class which reflects that it holds the global capability state of the app?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a more descriptive name here. When I read Capabilities.app it was not very clear what it means.
make a suggestion
Also does not need to be static?
yes, as it holds the capabilities of the running Bisq itself and is used in multiple places all over the code.
Should the class extend HashSet instead of using the field capabilities - as that is basically what it holds?
see below
@Setter | ||
private static List<Integer> supportedCapabilities = new ArrayList<>(); | ||
public void resetCapabilities(Capabilities capabilities) { | ||
resetCapabilities(capabilities.capabilities); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capabilities.capabilities reads strange. If we would use a HashSet as super class i think it becomes more natural.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I thought about that but having Set
as superclass adds all the methods as well and well, makes the whole Capabilities
class superfluous which then results in handling capabilities like a set. I do not know if we want that.
resetCapabilities(capabilities.capabilities); | ||
} | ||
|
||
public void resetCapabilities(Collection<Capability> capabilities) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would replaceCapabilities be better than resetCapabilities? With reset I would expect more the clear funtion rather then the additional add.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm interesting. A setCapabilities
seems to me clear as it replaces all capabilities, a resetCaps
indicates more strongly, that the capabilities are going to be replaced. I would understand a clearCapabilities
as a clear without add.
Again, in a collection of event logs, a reset clears the log.
Hm. setCapabilities
or simply set
?
Got rid of the Capability ordinals being used all over the place - a first and major step towards a cleaner, more readable Bisq code base where Bugs have less places to hide. (Done in my intention to clean up the p2p part)
Doing that I even managed to remove some 60 loc: some stats using
github.com/AlDanial/cloc v 1.80
EDIT: after a quick chat with @ManfredKarrer I did some more refactoring...
Note
this is a fairly big change where functionality should remain the same. However, this needs thorough testing.
My suggestion is that every reviewer of this PR should have a testing session with me where we do the basic things such as a simple trade so major bugs are discovered before merging.
In-depth testing is done anyhow before the next release...