2

I don't have compilable code, because the code in question depends on a large function that's irrelevant to the question, but say I have the following scenario:

savePath = "C:\\..."

changePath1, changePath2 :: String -> String

changePath1 passedPath =
    'Do something with passedPath'

changePath2 =
    'Do something with savePath'

let newPath1 = changePath1 savePath in ...
let newPath2 = changePath2 in ...

Is it more proper to set up functions like changePath1 (where the global path is passed in), or changePath2 (where it just internally uses the global path) If the functions had a chance of processing more then 1 path, obviously I'd use changePath1, but in my current program, there is only 1 path to deal with, so it seems simpler to just have all the functions internally know the global path instead of constantly passing it in.

Thank you

4
  • I didn't understand the question, but here is a list of windows environment variables, I think they may help you. askvg.com/… Jul 9, 2014 at 17:12
  • 2
    @AndrewHoffman The question is whether or not to have a function depend on a variable as a global constant or to have it be passed in as a function argument.
    – paul
    Jul 9, 2014 at 17:14
  • @paul thanks. Carcigenicate Does the language support optional parameters? In c# your function could be changePath(string savePath = "C:\\..."){/* do work */} Where if no path is passed, the default is used. Jul 9, 2014 at 17:19
  • @AndrewHoffman Haskell doesn't has optional parameters available stock. I know I've seen people hack together solutions, but it's not necessary typically. Haskell functions work different then most languages (They're "curried"), and optional parameters just don't fit the language well. It basically boils down to "Is it typical in small programs to rely more on global constants to keep the code neater, or should everything be passed for possible re-use and flexibility?" Jul 9, 2014 at 17:37

4 Answers 4

2

Is it typical to hardcode values? Yes. Most software is hastily written and never leaves the harddrive it is compiled on, so it doesn't matter.

However, if its software that other people are going to use and install, and you want to be able to configure where something is saved, it usually goes two different ways based on who is configuring it.

However the question isn't about these scenarios. The question is if it is typical for small programs to save to a path that is stored as a global variable as opposed to passing the value in.

My answer: Yes it is typical.

2

Do you foresee ever wanting to change the value of savePath? If so, it should be passed in as an argument to your functions. (Even though your functions would all only process a single path, you might want its value to be dynamic within the program.)

With a name like savePath I could foresee wanting to change that via a command-line argument or pulling it in from a configuration file -- while keeping a hard-coded default. In these cases having it as a global constant wouldn't work.

Personally I prefer to have things like that passed to my functions so that they're autonomous from the rest of the code, but that's me. (When passing things like that around as an argument to functions becomes too painful, you can employ the State or Reader monads to help, though that cuts down on the autonomy.)

6
  • I won't need the ability to change the path. It's just a small Rock, Paper, Scissors game that saves your running score against the computer. The question is basically, is it typical in small programs to rely more on global constants to keep the code neater, or should everything be passed for possible re-use and flexibility (and clarity)? Jul 9, 2014 at 17:49
  • @Carcigenicate Most of my programs grow, so I tend to make things parameterized, but if that's not the case for yours then a global constant should be fine -- this is just one of those design decisions that needs to be made. (You can always refactor later.)
    – paul
    Jul 9, 2014 at 18:20
  • @Carcigenicate One thing you might want to consider is naming: if you're passing the path as an argument then you'd want to use changePath, but if you're not passing it as an argument and the changed version might make more sense as changedPath, making it more of a constant itself (assuming it didn't take any more arguments than the path).
    – paul
    Jul 9, 2014 at 18:21
  • This is, in reality, a terrible example of what I was trying to achieve. I tried to greatly simplify it so it would make more sense in this context, but I didn't put much thought into the naming (my bad). You're right though, and I usually try to put more thought into good, descriptive names. Jul 10, 2014 at 19:55
  • I always struggle with naming things myself and have been a bit of a stickler about it recently (much to the chagrin of some coworkers). It struck me the other day that not being able to come up with a good name might be indicative of not having reduced the concepts I'm working with into manageable bits -- I'll have to watch out for this and see if it's the case.
    – paul
    Jul 11, 2014 at 12:16
2

In Haskell in particular, you can have your cake and eat it, too!

changePath2 :: Reader FilePath FilePath
changePath2 = do savePath <- ask
                 -- do stuff with 'savePath'

changePath1 :: FilePath
changePath1 = runReader changePath2 "C:\\..."

For this trivial example, of course, you could just as easily use an ordinary function rather than Reader, but using Reader scales up to much more complicated "static dependecy injection"-style things that this example only gives a glimpse of.

1

If a program is "small" does not matter. What matters is if your program is just a game or throwaway tool for yourself, or if you develop this for the production environment of your employer.

If the latter is the case, chances are high the program, even if it is initially "small", may be used for several years, and there will be a high chance that it has to be adapted to changing requirements. The latter means that sooner or later there will be a need for unit tests or regression tests. And functions which depend on global variables are inherently harder to test than pure functions, which should make the decision clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.