Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

KISS vs Feature set

by Masem (Monsignor)
on Jan 25, 2002 at 17:39 UTC ( #141494=perlmeditation: print w/replies, xml ) Need Help??

I was in the process of tidying up my File::Grep code last night and came across a dilemma. I've redone most of the code such that using closures, the main grepping routine is located in one single function, and the user-callable functions simply need to call that with their closure. Thus, besides fgrep, I was able to implement fmap (analogous to map) and fdo (analogous to a foreach statement, but of a form consistent with fgrep/fmap). I mentioned in my original post here that I was considering adding other functions to provide more features, but that was before I rewrote the code to provide better hooks.

One example was that in the case where the fgrep was called with wantarray, the sub would have returned an array of hashes, one for each file in the list. The hashes had the number of matches, the matches themselves, etc. However, I realize that some would have not wanted the results back that way, instead, just wanting a flat array. So I was considering writing an "fgrep_flat" function which would return that array. However, given that I've provide 'fdo', it's just trivial for the user to create this functionality themselves if they need it. So theorhetically, there's no need for me to include it.

A second example is that array of hashes itself. It would be documented in the POD of course, but it requires the user to know what to expect from it. Alternatively, if I simply had fgrep return an array with the matches in it, there's no question what fgrep would return and would make it very simple. If a user really wanted a detailed set of information from the matches, he could simply use fdo or fmap to create that set for himself, and with the specification that he wants.

Adding the additional functions would of course not affect performance in any way, but would have to make assumptions about how the user is accessing the module and their data. It would seem to me that in this case, it's better to follow the KISS (Keep it Simple, Stupid) policy and only provide, strictly, the fgrep/fmap/fdo functions, and allow the user to modify their code to meet what they want, itself of trying to guesswork at what the user wants and provide functions that increase the functionality but with possibly odd return types.

So in general, it would seem to me that if you have the option of adding more functionality to something but at the cost of having to guesswork how the end user would handle it, it's not a good idea. But if the return type is straightforward (a scalar, a list, or similar) that requires little explaination, it can't hurt to include it (as an example I point to DBI's fetchrow_ functions, only 1 which is really needed, but the others are more efficient but don't have difficult return types).

Any other rules of thumbs or suggestions on this (for the module itself or in general?)

Update in can

Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
"I can see my house from here!"
It's not what you know, but knowing how to find it if you don't know that's important

Replies are listed 'Best First'.
Re: KISS vs Feature set
by AidanLee (Chaplain) on Jan 25, 2002 at 18:04 UTC

    First off, I agree with the first sentence of your last paragraph. And it wouldn't hurt to provide multiple WTDI in the module itself if you forsee them useful to a large segment of your users (if you have a pretty good idea lots of people want it, and it "fits" within your module's domain, then you're tactically circumventing a lot of reinvented wheels).

    What I *would* suggest for your specific module, is to make the simplest case the default one. You're mimicking command line calls, so it's best to not "expect too much" from your implementations. So, IMHO, fgrep gets to return the array of matches, fgrep_hashref gets to return the AoH with the extra meta information.

Re: KISS vs Feature set
by hsmyers (Canon) on Jan 25, 2002 at 18:31 UTC

    It's hard to go wrong with KISS as a basis. The successful design of a module (or library (or interface)) pretty much depends on either experience or empathy or both. This is basically a 'walk a mile in another's shoes' kind of thing and efforts to expand functionality beyond a simple model quickly fractalize into complexity. That said, another area to explore lies below the obvious user level, i.e. below fgrep etc. Sometimes it is not the higher functions a user wants, but rather the primitives used to build the higher level. If these are exposed clearly and cleanly in the module then you appease the user who wants a portion of what you've designed, but has something else in mind in terms of what to use it for. This is surprisingly difficult to do in a generic and style free manner. Which last brings up an important criteria for evaluating the entire module. Namely, how much does the intended user have to think like the module author in order to use the module? Obviously this should be minimized as much as can be without diminishing function.

    So, short answer, yup KISS is good, elsewhere there be dragons!


    "Never try to teach a pig to sing…it wastes your time and it annoys the pig."
Re: KISS vs Feature set
by little (Curate) on Jan 25, 2002 at 19:07 UTC
    Note: my english is not as good as it might look like, so if anything I write here might have more than one meaning and one of those could be taken offensive I just mean the other one, which does not :-)

    I'd go always with KISS, as thats the perlish way.
    I mean a lot of Perls magic comes from the fact that "what you give is what you'll be returned".
    So the reason to go for KISS is simply to keep it common, eg. I should have the same expectations to your modules that I have to core modules.
    Many functions act different on how they are called, but they do it consequently, so I'd suggest: if caller passes a ref so return a ref, if caller expects a string (scalar context) return the length of the array that would have been returned if the function would have been called expecting an array (list context) to be returned.
    If called with an arraref return the ref to the resulting array.
    At least in this way also 'baby perl' coders will be able to use your module.

    Have a nice day
    All decision is left to your taste
Re: KISS vs Feature set
by footpad (Monsignor) on Jan 25, 2002 at 21:22 UTC

    A former employer preferred the acronym "LAW" (Least Amount of Work) over "KISS." 1

    On its face, it seems like pure semantics. However, there is something to the mental shift. First, few people enjoy being called stupid. Second, if you reduce the amount of work needed to create, maintain, or use something, then you've done a good job. This is the heart of Laziness as a Perl virtue. You don't take shortcuts in your work, you work to provide shortcuts. After all, if software doesn't make something easier, cheaper, or better, then why are we writing it?

    Personally, I'd go with keeping the fgrep/fmap/fdo functions and providing an example for your "fgrep_flat" function in your Usage/Examples POD.


    1 - He also preferred to say "Well, if I win the lottery..." instead of "Well, if I get hit by a bus..." He had this thing for putting things positively. At the time, I tended to get annoyed at what I called "optimistic sugar-coating;" however, I've since begun to realize that while it's good to plan for the worst, you don't necessarily have to be a sourpuss about it. YMMV.

      Just to clarify this, I would combine KISS and LAW, such that fgrep would simply return a flat array in wantarray mode. Hardly any work on my part and it's very simple to remember. And then I'd include the example of building up a hash using fdo, if so desired.

      (Gah, KISS and LAW, what is this, the Ally McBeal School of Programming?? ;-)

      Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://141494]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2017-12-16 21:40 GMT
Find Nodes?
    Voting Booth?
    What programming language do you hate the most?

    Results (459 votes). Check out past polls.