Comments (3)
Thanks @yusefnapora for the context dump, this is really helpful. Below are some of my thoughts on our use of Go interfaces generally and with the DHT/ContentRouting specifically that hopefully are useful (but idk you tell me 😄):
- Given that everything is theoretically a breaking change, like that article states, we should probably define what "breaking" means to us (go-libp2p)
- If we're going to change/augment the
ContentRouting
interface I would highly recommend combining it with theDiscoverer
interfacego-libp2p-core/discovery/discovery.go
Lines 18 to 21 in 0723374
- This interface almost exactly matches the ContentRouting interface, with Discovery being the more general one. I even made some wrappers for converting between ContentRouting and Discovery at https://github.com/libp2p/go-libp2p-discovery/blob/be2ad5297c88bc8db2f98334dfd4f0ae392e47a0/routing.go
- If the Discoverer interface is deemed insufficient we should toss it out and replace it with whatever works here since there are very few Discoverer implementations we'd have to update
- I'm pretty sure the go-libp2p-kad-dht interfaces could use some quality rewriting anyway (i.e. why does it have functions with a dependency on CIDs when it's just a distributed KV store), so I wouldn't feel bad about breaking the interfaces. We can always put together a backwards compatibility wrapper if anyone really wants it.
- Trying to write Java in Go
- I'm sure there are a number of us that got our Java experience long before our Go experience. Combining this with our desire to make go-libp2p extremely pluggable leads us to spending a lot of time designing interfaces that are globally defined (e.g. this repo)
- Go has a very opinionated view of how it thinks you should write code and that includes not using interfaces this way. On the Go Tour introduction it says:
Interfaces are implemented implicitly
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no "implements" keyword.
Implicit interfaces decouple the definition of an interface from its implementation, which could then appear in any package without prearrangement.
- I suspect that if we actually took their advice and moved toward defining interfaces where they are used instead of globally that we would be able to "break" things with fewer repercussions.
- If we're going to continue to use global interfaces
- Perhaps we should try and make them more extensible/generic. For example, we could return some interface representing an signed peer address instead of the
SignedRoutingState
struct. Not convinced here, but just a thought 🤷♂ - It might be helpful to use the option pattern in the interfaces so we break things less in the future
- Perhaps we should try and make them more extensible/generic. For example, we could return some interface representing an signed peer address instead of the
- If modifying
peer.AddrInfo
is much easier than any of the more interface-oriented approaches then I don't see why we shouldn't do that, but if we have time to explore why everything is harder it might help us in planning how we should redesign things when we can start paying down some of our technical debt 😜
from go-libp2p-core.
These are great points, thanks @aschmahmann!
As someone that's coming more or less straight from Java to Go, the interface thing has definitely been tripping me up.
I think that defining and using an interface instead of the SignedRoutingState
struct might also help me with testing. For example, in the identify PR I'd like to test how it behaves if signedRecord.Marshal()
returns an error. In java I'd use something like Mockito, but the Go way seems to be to define an interface instead, and have the test code provide an implementation that returns an error.
I also found this blog post about go interfaces that's pretty good. In the Upgrading Interfaces section they recommend defining a new interface with methods you want to add instead of adding methods to an existing one. Then the caller has to do a type assertion to see if the new interface is supported. I could potentially make it so that the Peerstore changes in #73 are non-breaking changes by adopting that pattern.
I'm intrigued by the idea of moving go-libp2p away from "global" interfaces... one of the things that's been tricky for me as I'm learning how to navigate go-libp2p is that it's not obvious where the implementations for a given interface live and where all the consumers are. That's partly because things are spread out into a lot of repos, but moving towards defining interfaces at the point of use would probably help. Sounds like a pretty big refactor, but definitely worth thinking about 🤔
from go-libp2p-core.
just had a sync call with @raulk, where we talked over this issue and realized that we may not need interface changes here. Instead, we can isolate the signed vs unsigned record exchange within the DHT implementation, and callers will still use the existing PeerRouting
and ContentRouting
interfaces.
If a consumer of those interfaces really cares about only having signed addresses, they should be able to enable a "strict mode" flag, which will prevent the DHT from returning unsigned addrs.
I'm going to close this issue, since it looks like we won't need to change the -core interfaces or peer.AddrInfo. I'll open a new planning issue soon in the -kad-dht repo to track the actual implementation changes needed.
Thanks again for the input @aschmahmann :)
from go-libp2p-core.
Related Issues (20)
- Host event bus does not emit EvtPeerConnectednessChanged HOT 5
- Error in using libp2pquic.NewTransport with libp2p.Transport HOT 2
- Record envelope protobuf does not match spec HOT 2
- Add a `ClearDeadline` API HOT 4
- v0.7.0 breaks backward compatibility for multiple packages HOT 3
- add WithStat option for host.NewStream HOT 3
- Closing streams does not transmit all data HOT 1
- Unable to marshal / unmarshal AddrInfo within my struct HOT 4
- flaky TestResetBandwidthCounter test HOT 1
- How to know the conn has been closed
- What happened to the method in **helps**? HOT 1
- Reliable Notifiee events HOT 1
- looks unsafe HOT 2
- routing.go HOT 1
- How to convert PrivKey to crypto/ecdsa.PrivateKey? HOT 1
- Requesting release 0.16 with "update btcec dependency" change HOT 4
- btcec update leads to `go mod tidy` failure HOT 9
- extend `peer.Set` with the Remove method HOT 4
- Unable to know data on the connected node HOT 1
- use a mock clock in bandwidth counter tests HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-libp2p-core.