Verbosity to the point of unusability in generic graph class
I am trying to create a graph class, I'm using a lot of generics, it works fine but adding a weighted edge of weighted vertices is extremely unwieldy and basically unreadable.
This is insanely verbose but I have no idea how I could improve it without sacrificing type safety or versatility.
For reference, the weighted edge and vertex classes:
and the graph class definition for a directed graph
30 Replies
Presumably all edges and vertexes in a given graph have the same type? If so (and this one of the very few places where I'd advocate this), having
Vertex
and Edge
by child classes of Graph
would cut down on the number of generics flying around
Some factory methods on weightedGraph
would help a lot, maybe? Though just fixing the signature of AddEdge
would also help
Oh I see, you're allowed to substitute in any kind of edge and vertex. Why?
And are you really instantiating 2 new vertexes every time you add a new edge?Well, if you want a graph with mixed weighted and unweighted vertices of course! :D
Your implementation doesn't let you mix weighted and non-weighted edges/vertexes, though?
Uh yes you're right I thought I was already at this step, let me re read that.
You're saying I should have
DirectedUnweighted
, DirectedWeighted
graphs etc.?Coming at this from an API standpoint, I would have thought that your API surface would be:
* Add a new vertex
* Add a new edge connecting two existing vertexes?
In which case your methods are:
*
VertexType AddVertex(T value, TWeight weight)
* EdgeType AddEdge(VertexType vertex1, VertexType vertex2, TWeight weight)
I'm challenging how much complexity you want to have. Do you really need a user to be able to provide any sort of edge/vertex type they want?
If not then yeah, having separate weighted/unweighted types would simplify the API a lot (they can still share a chunk of code -- you can still use your generics behind the scene)What do you mean by "sort" of edge/vertex type? I only need the vertices and edges to either have weights or not
As in, with your current impl, I could do
new DirectedGraph<string, MyFancyVertex, MyFancyEdge>
, where I've defined MyFancyVertex
and MyFancyEdge
myself. Do you need that?Mh, no, indeed I don't plan on creating new types of vertices or edges, I didn;t include them but the only other class implementing IVertex is an Unweighted one and the only other class implementing IEdge is the same
Then you don't need to expose that to the user IMO
Alright I see what you meant
(You can still use your
DirectedGraph<T, TVertex, TEdge>
in the impl, to share code between the weighted and non-weighted graphs)This doesn't allow the user to have weighted edges/unweighted vertices though
That's true
Well I maybe go that route then, I'll sacrifice some versatility I guess
Other thoughts: target-typed
new
can help
weightedGraph.AddEdge(new(vertex1, vertex2, value))
Is that implicitly creating a class corresponding to what is asked by the function?
It works out what to instantiate based on the signature of the method, yeah
Well, that worked
It looks...hard to parse though, would that be an acceptable fix?
Yeah, I've no idea what's going on there
And I can't overload the method AddEdge now
But it is really expected that you'd add 2 new edges and a new vertex at the same time?
And
new
up the values at the same time?Well, I need two vertices to create an edge, new or not
Right, but if you're not
new
ing them in that expression, it's easier to parse
weightedGraph.AddEdge(new(vertex1, vertex2, new(value, 0)))
You could also use extension methods:
Then you can do directedGraph.AddEdge(vertex1, vertex2, value, 0)
Alright gimme a moment
Would that reside inside the graph class?
That'd have to be in a separate
static
classNot super keen on making this a static class unless I'm missing something, I was starting to think about factories to be honest
As in, your extension methods need to be in a separate static class
That's how extension methods work
public static class DirectedGraphExtensions
or something
Then that can call directedGraph.AddEdge(new ...(vertex1, vertex2, new ...(value, weight))
And you can have different extension methods with different combinations of WeightedEdge
, non-weighted Edge
, etc. Intellisense will only suggest ones where the signature fits the type of DirectedGraph
Very well, I'll read up on extension method and try to implement that then
Thank you for your time, really
For problems like this, I like to start with designing the API, then work from there
So figure out how the class should be used first. That's the bit that people care about.
separating the builder part of the API from the graph class may also be a thing to consider