23 October 2017

Functions as First Class Citizens

So I've been doing a lot of thinking and reading on the notion of functions as a first class citizens. In Python, functions are objects, just like instances of classes are objects. So when do you create a class and when do you create a function? 

In my mind its somewhat a matter of style. That is, there is no mandate to use a function in place of a whole class or vise versa. That said, there are certainly times when a class is way too much work and a function will do just fine.

So a function doesn't have state, or at least it shouldn't. That means anything it knows about the world it gets as an explicit or implicit argument. Explicit arguments come in the form of parameters just like you would expect. Clearly implicit arguments should be constants or retrieved values and should never be global variables and the like.

Once you have written your function you can feel free to import it, call it, pass it around. It is pretty handy to not have to instantiate something in order to get some functionality. BUT, is this all necessary?

Again, I think we get back to a style question. I grew up on C/C++/Java with a little Perl thrown in. Discounting structured programming, in my mind everything should be an object and every object should have a class. That is clearly a habit born of Java. 

I would not be critical of an application full of objects. I would not criticize a developer for never having a stand alone function. That kind of style question does not register in my lizard brain as a concern. 

As I continue to play with the idea of functions as objects and functions standing alone I find myself questioning a lot of what I've learned to believe about good design. The biggest issue that occurs to me is, functions just laying about feels disorderly. I have to remind myself that the Python concept of 'module' as a means of organization has some significance. Think module == classy and it feels a tiny bit better.  

Anyway, there is certainly some utility advantage to having free standing functions. For one, no tedious object instantiation. Another benefit in my mind is, you don't have to prefix a function with self. That is one of the least pleasant things in Python in my mind, all this self prefixing (same complaint about OO-Perl etc.). So if typing has somehow become the hinderence to your success, using standalone functions will save you some of that. 

One other thing, in the past we've had this issue of 'where do I put utility functions'. Like convert_to_utc(datetime), a function that given a datetime in some timezone will convert it to the UTC timezone. That doesn't need a utility class, we don't need/want to do Utils().convert_to_utc(datetime) and so the function cleans that up, making it just convert_to_utc(datetime). That is one aspect of the function as a standalone/first-class object that I do appreciate. No more 'common' or 'util' classes cluttering things up.

I have some other thoughts I'll share in future posts but for now, chew on the idea that functions can be first-class citizens in your program.