bobbyalex
bobbyalex

Reputation: 2751

Choosing specific vs generic methods

Which would be a better design for a public interface:

WriteValue(DeviceValueType.MachineName,"micks machine");

OR

WriteMachineName("Micks machine");

If you use type 1 then you just need one such generic interface and you can write to any number of DeviceValueTypes just by adding items to the enum.

The second type is more specific in that it will write only a value to specific type denoted by its method name. But these methods have a great advantage with respect to type safety.

For eg: Lets consider another type

WriteValue(DeviceValueType.SleepDelay,"25");

and

WriteSleepDelay(25);

Note that here, type 2 has an advantage because I can specify the type expected. If I were to use type 1 then I will have to cast the value to int and then throw an exception if the value is not in the expected range. If I had to pass complex types, this becomes even more difficult.

So in summary:

Type 1: Generic. The interface will need to expose only one method. No type safety for parameters. Type 2: Specific. The interface will require as many methods as there are types. Type safe.

What is the generally suggested methodology to solve this problem?

I am using C# but I believe this problem to be non language specific.

Upvotes: 3

Views: 500

Answers (4)

Lodewijk Bogaards
Lodewijk Bogaards

Reputation: 19987

You should avoid what you call type 1 interfaces. Speaking from experience, these kind of interfaces tend to get messy pretty fast. Take the sleep delay example. How are you going to type check that string for a positive integer? You will end up with a huge switch statement. So at the very least encapsulate it.

Although your type 2 is better it should be noted that it tightly couples the write action with the data needed for the write. I don't know the requirements you are dealing with (write once read many?), but your DeviceValueType enum suggests you could simply declare a DeviceConfig class with properties like machine name and sleep delay and pass that to a Device or DeviceWriter class that will do the actual work. However, if machine name is config, while sleep delay is actually a method you should consider separating those two concerns as well (i.e. Device.sleep() and Device.writeConfig(DeviceConfig)).

Upvotes: 1

Andy
Andy

Reputation: 1994

First of all: I don't know a general rule, or a design-pattern for that situation, therefore I write what I would do.

If you don't care about the parameter's type, do something like this WriteValue("micks machine");. But than don't do any tricks like formatting integer differntly than strings, etc., just plain write the string you get and let the caller do translations. (type 0)

I would never do something like your type 1. Why? you mentioned some reasons (type-safety). But also for readability: you would end up doing swtiches or if-then-elses. And, if you care about clean code, you would also end up writing private helper methods with a signature like WriteMachineName("Micks machine"); (as in type 2).

I would prefer type 2, maybe mixed with type 0 for simple types, e.g. WritePlain("Micks machine"); WriteNumber(3.4);

Note: in type 1 and 2, you move some of your business code to those methods. That's neither good nor bad, but you must choose if it is applicable for your case (coherence). In contrast type 0 keeps the transformation-logic from a type to a string within that class.

Upvotes: 0

creinig
creinig

Reputation: 1580

It depends :)

Also, a third possibility would be to do both: Have a generic WriteValue() and a specific 'WriteSleepDelay()which in turn callsWriteValue()` with the correct parameters. This can make sense if the implementation of these methods is rather complex, i.e. if you'd have much redundant code unless you concentrate it into the generic method.

For a (presumably) simple thing like WriteValue I'd go with separate methods for simplicity.

Update: For an inheritance hierarchy it would make sense to have the generic method in the base interface. The derived classes can then add additional type-safe methods (e.g. WriteSleepDelay()) that make sense for them only.

Or you might want to have a WriteValue(Object value) in the base class that's overridden with an appropriate typesafe variant in the children (e.g. WriteValue(Integer) in child class SleepTimer). Most likely this won't make sense in your concrete case, but for other situations it can be ideal.

Upvotes: 0

Xudonax
Xudonax

Reputation: 439

I'm coming from a Python background, but I would actually pick both options. Make the WriteValue function, and let it do all the heavy lifting. Then, write the WriteMachineName and WriteSleepDelay functions as simple wrappers around WriteValue. This way, you'll be able to use the shorthand function for all functions that are used often, and the long version for everything that isn't called that often.

You might want to make the way this works explicit in the documentation though, so people who'll have to work with it after you know how and why you did this.

Also: I don't know how expensive function calls are in C#. If they are very expensive (in CPU time), you might want to always go with type 1.

Upvotes: 1

Related Questions