Steven Evers
Steven Evers

Reputation: 17196

Suggestions for how to clean up this API

For a fun project I'm trying to implement the BitTorrent spec, and right now I'm working on the BEncoding portion of it.

The encoding basically can encode from int/string/dictionary -> string for transmission. I've got all of the different encodings written/tested/working as overloaded Encode(...) methods and I've got the individual decode methods written/tested/working as DecodeString(...), DecodeInt(...) etc.

I can't figure out a way to have 1 Decode method for all decodings, in order to keep the API for the encoding/decoding as clean as possible (2 public methods, tops, for the time being).

Note that I have a method that can get the type of result that the decoded string will have.

Client code, right now would have to look something like this every time they want to decode a message:

string s = ...; // Encoded string
Type t = Encoder.GetDecodedType(s);
if (t == typeof(int))
    process(Encoder.DecodeInt(s));
else if (t == typeof(string))
    process(Encoder.DecodeString(s));
else if (t == typeof(Dictionary<string, string>))
    process(Encoder.DecodeStringDictionary(s));
else if (t == typeof(Dictionary<string, int>))
    process(Encoder.DecodeIntDictionary(s)):

and I'd like to be able to clean that up to be more like:

string s = ...; // Encoded string
process(Encoder.Decode(s));

where, in both cases the process(...) would likely be overloaded functions at the client end taking the 4 types of decoded values.

Upvotes: 1

Views: 141

Answers (4)

Joel Martinez
Joel Martinez

Reputation: 47749

If you are writing a library/framework ... this will be the most invaluable resource in your endeavor :-) I have the hardcopy and read it cover to cover:
Design Guidelines for Developing Class Libraries from Microsoft

Upvotes: 1

Timwi
Timwi

Reputation: 66573

You could let the DLR do this for you.

public static void Process(int i) { ... }
public static void Process(string s) { ... }
public static void Process(Dictionary<string, string> dic) { ... }
public static void Process(Dictionary<string, int> dic) { ... }

[...]

public dynamic Decode(string input)     // or 'object' if you prefer
{
    var t = GetDecodedType(input);
    if (t == typeof(int))
        return DecodeInt(input);
    else if (t == ...)
        // ...
}

[...]

string s = ...; // Encoded string
Process(Encoder.Decode(s));            // if you used 'dynamic' above
Process((dynamic)Encoder.Decode(s));   // if you used 'object' above

Upvotes: 3

Aaron McIver
Aaron McIver

Reputation: 24713

I'm confused. why not simply perform the GetDecodedType logic in the public Decode method and determine the type and then make the varying calls once determined?

Upvotes: 0

Woot4Moo
Woot4Moo

Reputation: 24316

I would say that you should follow the Liskov Substitution Principle here and create a method for each data type. That way you don't keep adding to the misery of utilizing typeof when you start passing custom objects. After reading over your question again, you already know the type being passed to it, so that further supports the need to remove the typeof operation

Upvotes: 0

Related Questions