Object-Oriented Programming
In OO programming, everything is an object with two aspects: data and behavior. Objects have data (fields, members, attributes, etc.) which are either simple date types (int, String, boolean, etc.) or are objects themselves. You can get and set these values any time you can get a handle on the object, assuming the object implements a way for you to be able to do that (either directly or through accessor methods).
For example, an object in Java might look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Person {
private String name;
public Person() {
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
In this example, I can set the “name” attribute on a Person object whenever I want. Any other piece of code could, too. A particular instance of Person may or may not have a value for “name.” A particular instance of Person will remain in memory for as long as something keeps a reference to it, or until the application shuts down. I can have one part of my code pass a reference to this object to another part of my code. In fact, typically one part of code would set the “name,” pass the reference to of the object to another part of code which would then get the value of “name” off of that object.
In OO programming, the entire system is basically a huge state machine, where objects are created and attributes set, and then the objects are passed around or referenced by other code. The application keeps track of all the object in memory and program execution passes from one object to another, setting data on objects along the way. And programmers are all too familiar with what happens when program execution is attempted on an object that doesn’t actually exist: the Null Pointer Exception.
All sorts of best practices have evolved around creating maintainable, stable, and performant applications based on the characteristics of OO programs. However, in functional programs, the characteristics are different. So not only are there different best practices, the best practices in OO may be worst practices in functional programming.
Functional Programming
There are no objects in functional programming that have attributes and behavior (at least not in XQuery). Data and code are totally separate. Functions control program execution, and while they can receive data in, they themselves do not have fields or attributes. Functions operate on data and pass the data around by value. Once a function passes some data to another function, that’s it. The sending function cannot keep a reference to the data; it passed the data. The receiving function cannot even modify the data. It can, however, create a new copy with modifications, and send that to another function or return it back to the calling function.
Some of the advantages of Functional Programming are:
Nothing can change your data. Once you get it, you’ve got your copy and it’s yours. Nothing can mysteriously change it while you are operating on it. Conversely, a function cannot affect data other than what it received (no side effect).
It’s threadsafe. There are no concurrency issues since nothing can have a reference to the same data. There’s no way for one function to interfere with the data in another function. And there’s no way for code to have stale references.
No Null Pointer Exceptions. NPEs happen when a piece of code knows the definition of an object (its class) but makes the mistake of trying to invoke methods on a non-existent instance of that class. In functional programming, there are no object instances of code. Function signatures are checked statically and then called, so there’s no chance of a code instance not existing, once those functions have been imported.
Expressions can be compounded. This one might take a little effort to grasp at first. Since there are no instances of objects, and since all data is always passed by value from one function to another, then you can have once function call another function and so on without having to worry about instantiating objects or checking for null values. I can pass a string value to substring function to a concatenation function to a parsing function to a date constructor to a date formatter, etc. So my code can be made of compound expressions that elegantly build the logic I need, rather than having to write a new function (or object or method) that does what I want it to do.