> Most business logic falls into this bucket, and that bucket really works best as a functional paradigm
There is nothing I can see here that calls for FP. You are still mutating the state of the world.
Just use a free standing function. That's like a method on "The world", which is the object where we should put most functions. Programming is easy. (Not: all the technical decisions behind it)
I explicitly call out the reasoning for using functional concepts here: recombination into new workflows. For instance, a student may only be able to register for 15 credit hours or less. However, an advisor can register a student for up to 20 credit hours. If done properly, this should be a very simple change within the workflow... Just swap out the verification function that's composed into the workflow.
I still don't see what's functional about this. Functional is about higher-order functions, currying, and so on. I'm not positive most business logic profits from that. What you describe can be achieved by swapping out a number (or more generally, data).
Of course, we can come up with a scheme that requires two validation functions that have more distinctive features than just some number's values. And in this case that might be implemented by parameterizing the function parameter. But, it could also be implemented with a switch for example, and often this approach is more maintainable. And then, you can also have pointers to functions in conventional programming languages. In general, the need for functional approaches is vastly overblown.
> I still don't see what's functional about this. Functional is about higher-order functions, currying, and so on. I'm not positive most business logic profits from that. What you describe can be achieved by swapping out a number (or more generally, data).
And a discussion about composing functions is a discussion about higher-order functions. Why is that not FP?
I mean, it all boils down to assembly in the end... Why not just do everything in assembly?
I'm finding little too your arguments other than what seems to be a pre-existing bias towards functional approaches being "overblown", along with various alternatives which of course exist, because every programming paradigm is capable of implementing arbitrary logic.
Some abstractions will help you do certain things. If you find yourself constantly duplicating and tweaking the same axiomatic logic to do different things, functional approaches are generally a more helpful abstraction than others.
I can give you a good reason why not to do assembly. It requires you to allocate storage for data by constantly swapping it in and out of a fixed number of places. It binds you to minute details of a specific architecture that don't matter in 99% of the cases. It doesn't have a facility for subroutine calls (one of the most successful abstractions for sure), requiring the programmer to redundantly encode a calling convention at each call site, which also affects register allocation. It doesn't allow you to give descriptive names to local variables.
I'm not positive that functional approaches can bridge a similarly distinctive gap. But I know that it's easy to get tempted down rabbitholes where we constantly restructure programs without measurable benefit, or make abstractions that we regret later on.
Instead, it rather seems to me like mainstream imperative languages adopt a few simple features where they make sense (or not). For example, sometimes it's nice and elegant to look up items using a predicate function, although usually I'll actually prefer the explicit for loop or such (but yeah, YMMV).
One more problem I see is as follows. It seems to me that assembly->procedural (compiled) languages is a step that improves encoding efficiency in a very "local" way. It's still pretty easy to contain and control these abstractions and make different decisions in other places, and still have the places interact easily enough. With more advanced systems, I'm not so sure. There are so many general, far reaching assumptions how computation should be done (language runtime, code generation, etc) that go beyond the mere constraints of the computer's architecture. I think these lead to a lot of isolation that is not beneficial.
> If you find yourself constantly duplicating and tweaking the same axiomatic logic to do different things,
Point is, I really don't. (I'm not sure what "the same axiomatic logic" is, but I don't find myself duplicating a lot of things). Actually, it often seems to me things are much easier and less redundant if we can just focus on the data and not get a type system or similar in the way. Of course there might be problem domains where things look a little different than I've experienced.
There is nothing I can see here that calls for FP. You are still mutating the state of the world.
Just use a free standing function. That's like a method on "The world", which is the object where we should put most functions. Programming is easy. (Not: all the technical decisions behind it)