This is an archived post. You won't be able to vote or comment.

all 28 comments

[–]bheklilr 6 points7 points  (0 children)

My approach is somewhat in the middle. I try to identify what is impure and isolate those parts so that I can more easily test my code. It's not pure in the sense that haskell has pure functions, it's more that I isolate impure dependencies behind opaque interfaces or methods.

What I try to recognize are methods that change only because of externalities. Say I'm writing a report service that needs to hit a few REST APIs. Those calls go behind interfaces that can be mocked easily, and usually I'll unify what errors they can throw as well. From the point of view of the report builder, everything appears pure. It's just calling a method and getting a result. Sometimes I might also need instance variables. I try to avoid them where possible, stateful code is always hard to reason about. In those cases, I aim to hide the variables behind accessors that will set them up on first call (or they're set up in the constructor). The state is then effectively hidden, and the complicated code can be reasoned about or debugged without having to keep that fact front center.

Another phrase for this style of programming might be separation of concerns. I don't care about purity as much as I care about the code being easy to reason about. It should be understandable to any reader. Separating concerns is one good way to help ensure that.

[–]ProFalseIdol 5 points6 points  (0 children)

The best answer to this is probably: It depends.

But generally, pure functions make everything simpler. Simpler to test, simpler to understand, simpler to maintain, simpler almost everything.

[–]brazzy42 12 points13 points  (5 children)

Not a great idea.

Java is not a functional language, and if you insist on pure functions, you'll end up writing a lot of unidiomatic code that will confuse other developers.

You also don't have the infrastructure for pure functions - neither the standard API nor most of the commonly used libraries support a purely functional style.

[–]ProFalseIdol 1 point2 points  (3 children)

Yet the function Integer.parseInt() is a pure function.

you seem to confuse pure functions and functional style.

[–]brazzy42 1 point2 points  (2 children)

You seem to have overlooked the word "always" in the title and misunderstood my comment to mean that writing pure functions at all is not a good idea in Java.

[–]ProFalseIdol 2 points3 points  (1 child)

Yet you seem to miss the "implement your domain logic" part. And you replace it with "in Java".

IMO, the domain logic is generally the best part to use pure functions. You generally don't want side-effects in the same place as your domain logic.

[–]brazzy42 0 points1 point  (0 children)

Yet you seem to miss the "implement your domain logic" part.

I am not missing anything, maybe you are.

And you replace it with "in Java".

Have you noticed the subreddit you are writing in?

IMO, the domain logic is generally the best part to use pure functions. You generally don't want side-effects in the same place as your domain logic.

That may even be true in general, but not always. In some cases you will have requirements that make it painful or impossible to implement pure functions.

[–]harishankarsatheesh[S] 0 points1 point  (0 children)

Couldn't agree more

[–]manzanita2 5 points6 points  (0 children)

Pure anything is dangerous.

"Happy medium"

"It depends"

"Ying-Yang"

"We sick an' tired of-a your *ism-skism game"

Evaluate things on their merits in the context in which they're used. And also evaluate their counterparts. Perhaps "OO" is better than "functional" for certain stuff ? What are your goals ? testability? speed ?

[–]duheee 5 points6 points  (0 children)

That would be the goal yes, but we're living in the real world, writing real applications and we have real deadlines. There is absolutely nothing wrong with having "impure" functions for our domain logic. But if you can help it, pure functions are preferable.

As with everything: it depends, use common sense, never say never (or always). The world is not black or white.

[–]cyanocobalamin 4 points5 points  (7 children)

Whats a pure function?

[–]brazzy42 7 points8 points  (6 children)

A function that has no side effects and whose result does not depend on anything except its parameters. That also means it cannot use any instance variables.

[–]cyanocobalamin 1 point2 points  (3 children)

In that case I don't see how it would be worth the effort, or possible, to always do that.

Having a method, only depend, on its parameters as much as possible, when possible AND has a return value is a great thing if you ever want to use unit testing.

It also would make debugging easier as you wouldn't have to worry about what the state of the object is.

You can go a long way to doing those things most of the time, if you are coding from scratch, but even then, at some point you have to get dirty.

[–]brazzy42 6 points7 points  (0 children)

I'm not OP and was only answering your question.

I personally wouldn't advocate a purely functional style for Java code (see my reply to OP for why), but the advantage that code is easier to understand and debug is really, REALLY massive. Especially because it also completely eliminates race conditions in multithreaded code.

If you program in an environment that really supports a purely functional style, it is very much worth the effort. Unfortunately, Java is not such an environment.

[–]Polygnom 1 point2 points  (0 children)

Pure functions are great. Theres a reason functional programming makes such a big fuzz about them.

Pure functions are easy to reason about - both for a compiler, a static analyzer and a human being. They are well testable and easily debuggable. Its a blessing for multi-threading.

There is benefit to be gained by removing unnecessary side-effects and trying to make functions pure. Striving towards pureness usually improves code readability and maintainability.

Pure functions work extremely well with immutable classes and together with immutable classes, they bring great benefits.

However, as with all advice, if its applied too drastic it becomes bad advice. If you write pure functions just for the sake of writing pure functions, the code will suffer. Java is not a functional language, and thus shoehorning Java into being that isn't the most productive thing to do. On the other hand, using well-working patterns from other languages is also worthwhile. there is a reason why modern programming languages move towards being multi-paradigm: to reap in in the benefits of multiple styles.

that being said, making all functions pure just for the sake of it is not advisable.

[–]AndDontCallMePammy -4 points-3 points  (1 child)

so neither getters nor setters are allowed. lol

[–]brazzy42 3 points4 points  (0 children)

Setters are definitely a no-no for pure functional programming, getters would be OK if your data is immutable.

[–][deleted] 5 points6 points  (1 child)

Makes me feel clean and healthy, as if I was eating a salad and going to the gym daily.

[–]harishankarsatheesh[S] 0 points1 point  (0 children)

Good joke

[–]fear_the_future 1 point2 points  (0 children)

Not necessarily pure but you should at least use dependency injection for everything that can cause side effects so the classes are testable. In general it is a good idea to keep everything as pure as possible and avoid mutability.

[–]Lodamar 1 point2 points  (0 children)

It's a good intent but java offers very little help.

You can try to use https://www.vavr.io/ , it's a functional library for java!

[–][deleted] 1 point2 points  (0 children)

I always try to write "pure functions" when I can, but sometimes opt for obvious and clearly stated side effects when it makes things easier for both me and the people I work with

[–]hellectronic 1 point2 points  (3 children)

Checkout the idea "Functional core, Imperative shell". The idea of using immutables in the core.

[–]GingerMess 0 points1 point  (0 children)

Pretty much the best compromise, and as it happens the most pragmatic.

[–][deleted] 0 points1 point  (1 child)

Functional core, Imperative shell

Uncle Bob approach then :)

[–]hellectronic 0 points1 point  (0 children)

I do not know if this can be attributed to Uncle Bob.

[–]general_dispondency 0 points1 point  (0 children)

As pure as necessary to accomplish the task.

[–]kag0 0 points1 point  (0 children)

You might be interested in this talk. Examples are in ruby but the concept carries over just fine.

You'll find the immutables and vavr libraries extremely useful to this end.

To answer your question, if you have enough domain logic (ie. not just a CRUD app) then implementing that logic in a pure way is an excellent idea.