Sometimes, I encounter opportunities, while adding a requested feature, to make a tool a bit more generic for other possible needs with very little extra effort. However, this is considered a violation of YagNi, but often seems like too good a bargain to turn down.
For example, suppose you are designing a string-handling library. Originally you have a Replace function/method with 3 parameters: the original string, the string to be replaced, and the value to replace it with. However, a request comes in to give it a scope of the first encountered match or every match. Rather than making this Boolean, we could have it be an integer to tell how many matches to replace. Zero or an omitted parameter would mean "all". Thus, without adding more parameters, we can get more ability just by going from a Boolean to integer.
There's no such thing as a free feature. It may be that in the future, you find you need to optimize this method, and you choose a new algorithm, which applies nicely to a single match, but not to an arbitrary number of matches. The point is that whichever direction you commit to will preclude other choices down the line. YagNi is intended to help you keep yours and your customer's options open as long as possible.
But the reverse could also be the case.
Another way to look at this is that if it's genuinely "free", it'll still be free later, when a need for it is discovered. If the choice is between doing it now and doing it two months from now, all else being equal, it's better to do it two months from now. If the customer hasn't asked for it, you've got more important things to do.
It may not be "free" later because one has to find, visit, and comprehend the implementation code again. It is easier to open a drawer and take two socks out than it is to open the drawer for one sock, close it, and then open it again for another sock. One may end up doing a mental sequential search twice on the drawer instead of once.
Secondly, the interface you describe above smells to high heaven, which oughta be a clue that something's not right. A method which has magic behaviour when a parameter has a certain value should be refactored into two methods. In this case, we might call them replaceOnce, replaceAll, and replaceFirstN, or something.
That's a CureWorseThanTheDisease in my opinion. Perhaps a compromise is two different named parameters. I have never liked functions/methods with variations tacked onto the end. The rules for what becomes a parameter and what becomes part of a name are not very stable and consistent. One could end up with CartesianJoins of sub-feature-driven names like "replaceAllIgnoreCase", "replaceFirstIgnoreCase", "replaceAllCaseSensitive", "replaceFirstCaseSensitive" and so forth. (AttributesInNameSmell)
[And 90% of the code between all those functions will be the same anyway, so you'd factor it again by rolling it all into... a common function with multiple parameters. If the multiple functions suits your API esthetics better, it's easy enough to expose that as (an additional|the) interface. A place I've commonly seen this is with Show(bool show), where Hide() maps to Show(false).]
This brings up an interesting question: should having a good interface or easy implementation dictate the API design (assuming they produce different answers)? -- top
[I think it depends very much on what you're writing and who your customers are. I also don't think there's any perfect hard & fast answers, especially when it's something as subject as a "good interface". Personally, even in my own code, I tend toward clean interfaces at the expense of implementation. Incidentally, functions like the above are one of the reasons I love named parameters so much - it makes calling the function much more clear (you have "ignorecase=True" rather than a magic number) and it future-proofs the implementation (because you can add more named parameters without breaking existing code).]
EmulateKeywordAndDefaultParameters
[EditHint: Note, I wish to remove this example. It brings up too many other issues not related to BFP such that it doesn't serve the original purpose. But, first we need to find a home for this material. I don't wish to delete others' text without their permission.]
{Nah. Just delete this crap. Most of it is invective-filled junk that won't do anyone a whit of good even if it is true.}
Boolean function constantExists(group, constantValue) {.....}I then realized that if it returns the constant description instead of just a Boolean, it can serve future uses also. True, it may make IF statements slightly longer for the original usage, but worth it in my opinion.
if(constantExists("foo","BLU")) {....} // original use if(!isBlank(lookupConstant("foo","BLU"))) {....} // revampedIt provides more information for a small price.
[WTF is this spaghetti code? It provides more info for a small price? A nested double call of two functions... More info for what? To take away from readability to confuse other programmers reading the code? How is "not is blank lookup constant" more readable than something obvious like... isConstant? What is "blank", an empty string? A null? Both? How can a constant that doesn't exist be blank?]
I use this style all the time and don't have any problem with it. I can read my own code many months down the road. If you don't like it, just say so rather than accuse me of drug use. It's coming across as PersonalChoiceElevatedToMoralImperative. If you can prove it objectively "wrong", please show the proofs. (Note that I've used multiple dynamic languages that don't have explicit nulls, by the way, and I don't miss them. Nulls are a poorly thought-out concept in my opinion.)
I will agree that if one has to use lots of constant existence checks in the code, then perhaps a dedicated isConstant() function would be justified. But barring this, one function can do both look-up and existence checking. This is how one keeps a "clean tool box", and I like it that way. If you want to create a combinatorial explosion of tools, I don't want to use it myself.
And couldn't you still supply the constantExists() function simply by rewriting it as a call to isBlank(lookupConstant())?
{Or you could UseExceptionsInsteadOfErrorValues, have 'lookupConstant()' throw an exception on failure (rather than return a blank) and handle exceptions properly. Frankly, using 'blank' in the way you propose here is just as a "poorly thought out concept" as Nulls.}
Using exceptions for existence detection is a smell in my opinion. In fact, I think try/catch is a dumb gimmick. (There's already topics on that debate, so we don't need to have it here.)
Eff off! You have no objective proof, liar! Take your insults and shove them deep and hard.
I really doubt there is an objective right choice. Everybody has their own style and very few like other peoples' style. Its usually newbies fresh out of school who think their view is the center of the universe. Their ego has not been dulled down by reality (or lack of it) yet. If you don't like that style, just simply say so without personal insults. Don't pull a PersonalChoiceElevatedToMoralImperative and chew me out like you're the God of Truth and everybody else are your subjects. You are mortal like me with mortal preferences and biases. When Programming Truth Math finally comes out and points the one true way, then I'll re-evaluate my preferences. Until then, zealots like you can go to the very warm place in the basement.
You have a right to hate the hell out of my style. I hated others' styles also and cursed it internally. I've learned that people just plain think different and are tripped and confused by very different things. And I have changed my style somewhat based on feedback from others. However, it requires more than one person saying the same thing.
But as far as calling me a "charlatan" or a hypocrite, well that requires real evidence. Showing that I claimed that 2+2=3 in one message but 2+2=4 in another would be evidence that I am a hypocrite. (Past similar accusations merely turned out to be a miscommunication, by the way. I don't claim my writing is always clear, but I don't intentionally make it fuzzy. Some people just accuse first and ask questions later.) --top
What explicitly did I ignore? Anyhow, this is not the appropriate topic to bicker about such. (And you are partially right; my example of "hypocrite" was a sloppy one. My apologies.)
{Attempting to prove to you your own ignorance when you'd rather remain ignorant of it would be quite futile. If you really wish to know, there are dozens of pages in which you've participated where others and myself point such things out, where you shriek and whine about BookStops and MentalMasturbation as excuses to avoid comprehension, where you ask questions then become hostile to anyone providing an answer, etc. You'll need to become critical of your own behavior, and become considerably less ignorant, to even begin to understand most of these cases. Are you sure you're up to it?}
Blah blah blah, me bad you good, blah blah blah. Your evidence is very weak. It's that frippen simple. Even if I was the dumb rotting egg you claim, your evidence is still very weak. Come back with lots of scenarios and let's compare to the counter-scenarios and then put it on a scale to weigh them. You magnify little things into mountains in your head. You weigh wrong, or at least not carefully.
{Ah, but this isn't the page for it. The evidence has been entirely convincing on dozens of other pages, TopMind, where it has been pointed out to you repeatedly, where the evidence was immediate and strong, and where you (as usual) ignored it or found fallacious reasons to dismiss it. Even before I arrived, you were making fallacious arguments from a seat of arrogant ignorance. Heck, you're the only person on this wiki who has the dubious distinction of having a page dedicated to his fallacies - one contributed to by many wikizens. Maybe, someday, you'll convince me that you aren't an unprofessional hack - because your reputation is already in the gutter. As I've said, attempting to convince you of your own ignorance isn't particularly relevant; the only reason I intercede these days is not to argue with you, but to make sure that people take your often dubious advice with a truckload of salt - your style of vociferous ignorance is dangerous to people that lack the education to make proper judgements. Opinion offered without valid justification has no place in Computer Science, but that is all you ever offer. As far as your last comment: I haven't needed to 'magnify' anything - rampant stupidity is proven by a big and ever growing pile of individual 'little' stupidities, and is something you've provided all on your own. One way you attempt to defend yourself has always been to look at each individual piece of evidence and scream: "That's weak! that doesn't mean anything!" - but, really, it is the whole pile at once that matters to everyone else.}
Why don't you spend more time improving your evidence instead on how delusional I am and how smart you are. It gets old. You sound like every other absolutionist blowhard who comes sniffin' around wiki looking for a fight. The bloat and e-red-tape caused by heavy typing and dandruff tables also piles up to sludge-up the works. I've seen such crap with my own eyes.
{I prefer to focus my efforts and studies on computer science and computation theory. You can't reasonably fault me for not agglomerating instances of your stupidity across pages. But here is an example, from this page, that constitutes strong evidence of your arrogance and bigotry-induced stupidity: You are unable to provide a full list of the problems exceptions are intended to solve, but you judge them a 'dumb gimmick' anyway. That this is an instance of a habit you have for sneering at things you don't even understand would become obvious only when placed beside the hundreds of other examples scattered across this Wiki. Oh, and it seems you neatly just provided another example of your hypocrisy: You declare heavy typing causes 'bloat' and 'e-red-tape', but (a) you haven't defined 'bloat' and 'e-red-tape' despite the fact that you often demand or expect definitions of such things from others, and (b) you have never provided evidence for these claims. You might as well say: "TopMind is an idiot! I've read his words with my own eyes!"}
The feeling is mutual.