2

Currently I'm working on a vector class in C# and now I'm coming to the point, where I've to figure out, how i want to implement the functions for interpolation between two vectors. At first I came up with implementing the functions directly into the vector class...

public class Vector3D
{
    public static Vector3D LinearInterpolate(Vector3D vector1,
        Vector3D vector2, double factor) { ... }

    public Vector3D LinearInterpolate(Vector3D other, double factor { ... }
}

(I always offer both: a static method with two vectors as parameters and one non-static, with only one vector as parameter)

...but then I got the idea to use extension methods (defined in a seperate class called "Interpolation" for example), since interpolation isn't really a thing only available for vectors. So this could be another solution:

public class Vector3D { ... }

public static class Interpolation
{
    public static Vector3D LinearInterpolate(this Vector3D vector,
        Vector3D other, double factor) { ... }
}

So here an example how you'd use the different possibilities:

{
    var vec1 = new Vector3D(5, 3, 1);
    var vec2 = new Vector3D(4, 2, 0);
    Vector3D vec3;

    vec3 = vec1.LinearInterpolate(vec2, 0.5); //1
    vec3 = Vector3D.LinearInterpolate(vec1, vec2, 0.5); //2

    //or with extension-methods

    vec3 = vec1.LinearInterpolate(vec2, 0.5); //3 (same as 1)
    vec3 = Interpolation.LinearInterpolation(vec1, vec2,
        0.5); //4
}

So I really don't know which design is better... Also I don't know if there's an ultimate roule for things like this or if it's just about, what someone personally prefers more... But I really would like to hear your opinions, whats better (and if possible why ;) ).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Another option is to make an extension method, or take the `static` out of your first code block. – gunr2171 Nov 10 '13 at 19:16
  • 1
    I think programmers will be a better place for posting this question - http://programmers.stackexchange.com/ – Yosi Dahari Nov 10 '13 at 19:16
  • 1
    If you need help on design I think that may be useful to look at XNA for example or other library/framework. On XNA the interpolation is defined as a static function of the Vector3 class as you can see [here](http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector3.lerp.aspx) – Fabio Marcolini Nov 10 '13 at 19:18
  • @FabioMarcolini: Thanks :) . I know the design from the XNA, but I don't know if it maybe wouldn't be better to use extension-methods, even if those guys are paid for figguring out the "best" design and they don't do anything the whole day :P . –  Nov 10 '13 at 19:47
  • @Yosi: Thanks, i didn't even knew the site... What's the main difference between stackoverflow and programmers :) ? –  Nov 10 '13 at 19:48
  • 1
    programmers is more suitable to conceptual questions, like design patterns etc. – Yosi Dahari Nov 10 '13 at 19:49
  • @gunr2171: What do you mean? I've got two options: A static and a non-static method directly in the vector class or one extension-method located in a seperate class... Or would you combine those two things in any way? –  Nov 10 '13 at 19:50

1 Answers1

0

There is a lot of goodness linked in these answers Best practices and guidelines for designing an API

But the thing here is the following: Don't implement anything as a member function if it can be implemented externally by using the public API of your class. I can't remember where I read about that (probably that Eric Lippert guy) though.

Update

It was that Scott Meyers guy. When should functions be member functions? . Sorry Eric!

Example after comments

Following Scott's advice I'd implement LinearInterpolation, DotProduct, etc. in a separate static class called VectorMath or VectorAlgorithms as non-extensions. Afterwards I'd try to come up with code examples using that API -- probably lots of realistic unit tests. That should give me a good and solid feeling if the API is usable, efficient and terse. If it turns out to be clumsy: Go against Scott's advice. Just make sure to get the evidence first.

Community
  • 1
  • 1
Jonas Bötel
  • 4,452
  • 1
  • 19
  • 28
  • 2
    I don't think I said that. Extension methods were designed specifically for the situation where it is difficult or impossible to add a method to a type, but possible to create a method based on the public surface of the type. In this case the original poster *can* add methods to the type, and that implementation can take advantage of private details as well. The question here it seems to me is whether or not the interpolation operation applies to objects other than vectors. In that case I would say: when you have three realistic examples, make the abstraction. Not before. – Eric Lippert Nov 10 '13 at 19:47
  • @LumpN: Ok, related to Scott Meyer, I should use an non-member method (well it's C++, but let's don't care about that at the moment), because everything can be done with the "public interface" of my vector class (am I right by now?)? But wouldn't it then be the next step, to implement methods like "Normalize" and "DotProdut" also as non-member methods? And in fact of C#, where everything needs to be stored in classes: Would be a static method in my vector class or an external method more "non-member-like"? –  Nov 10 '13 at 20:23
  • 1
    @EricLippert woah, I wasn't expecting you to show up (so fast). Please excuse my rude call. To me you are incredibly cool. Hire me! ;) On topic: There seems to be a fine line between implementing functionality as non-member non-extension vs. non-member extension method (emulating member functionality). I wonder if extensions should be regarded as members in the context of Meyers advice. FAIC? – Jonas Bötel Nov 10 '13 at 20:27
  • @LumpN: Yeah you'Re right... So we've got even one possibility more (if I understand you right): At first: make the interpolation a member-method of the vector class (non-static). Second: Also make it a member-method of the class (static). Third: Make it an extension-method for the class. Fourth: Neither 1 or 2 or 3: A completely seperate function in another class (static), performing the operation... But which is now the best in case of design and in case of usability? And how would you proceed with methods more related to vectors in general (e.g. normalization)? –  Nov 10 '13 at 20:35
  • 1
    @Benjamin you are correct. 4 options. I've updated my answer accordingly. Option 4 seems to be the least coupling, therefore promoting encapsulation (see Meyers). Strive for that. Prove that usability is reduced compared to the other options before considering them. – Jonas Bötel Nov 10 '13 at 20:53
  • Yeah, sometimes I'm just to focused on the correctness of the design and forget completely of usability... And I don't think it's very comfortable, to use a static method from total different class, in order to get the DotProduct or a linear interpolation.. So I'll figure out if I use extension methods or member-methods. But i think I'll go with a member-method, just because in my opinion, extension-methods have somehow the image of beeing functions, that a person, which don't have direct access to the source code of the class, can use, to extend the class :P .. Please respond if you dont agre –  Nov 10 '13 at 22:08
  • 2
    No worries, I was not offended. It is indeed a bit of a tricky call to make and I can see the merits of Scott Meyers' argument. Maybe I will do an article discussing the pros and cons. – Eric Lippert Nov 11 '13 at 01:15
  • "LinearInterpolate" is a helper-method of a vector in fact.. So may it's more about: Is it legit to "misuse" extension-methods as helper-methods? May you could implement the helper-functions in a different namespace to prevent "IntelliSense-Spam", so you can use them as static helper-methods or (if you want to) as member-methods... I really don't know how to handle with that... It comes more and more in my mind that that could be very useful. But whats better: Helper methods defined in a seperate class (maybe with extensions-methods) or as members (static and non-static) directly in the class? –  Nov 11 '13 at 15:23