5 ms·
> Tight coupling is the basis of oop. This is not what OOP people are talking about when they talk about tight or loose coupling though. They are talking abou
by chucksmash 2y ago
> Tight coupling is the basis of oop.
This is not what OOP people are talking about when they talk about tight or loose coupling though.
They are talking about the relationship between classes.
- ninetyninenine 2y agoAnd that’s the fundamental problem. They fail to see that if they took those same methods and made it independent of state then those things are now called functions. Functions can be moved to different scopes. Functions don’t rely on state to exist. You can compose functions with other functions to build new functions. And here’s the kicker. All of these functions did the same thing as the method. Functions are more modular. A method, is a restricted function that is tightly bounded with state and all other sibling methods.
- ajuc 2y agoThere's a trade-off. Functional programs are easier to read, because the structure makes the state transitions and dependencies obvious - you see your dependencies in the arguments list. But it forces you to basically rewrite big parts of your program after even very simple changes. You had the structure of the program so fine-tuned to the dependencies of every part of the code - that when any dependencies change you have to completely change that structure. It's rewrite-only programming style. Imperative (and OO) programming idiomatically let you do a bigger mess with side effects, and you know less about the data dependencies just from looking at the function specifications - but it also allows you to do exploratory programming much faster (no need to pass a new argument down 20 levels of your call stack when some code deep down suddenly requires a new argument). And it allows you to modify the behaviour locally without refactoring the whole thing constantly. If you have a for loop that filters out even numbers and suddenly you want to sum the numbers and find maximum and minimum too - most of the code stays the same. If you have functional code doing the same and want to modify it in similar manner - it's a completely different code. Most people would just rewrite it from scratch. And that's just a very small scale example. With larger programs the rewrite gets harder. That's why big programs are almost never functional.
- ninetyninenine 2y ago>Functional programs are easier to read, because the structure makes the state transitions and dependencies obvious - you see your dependencies in the arguments list. But it forces you to basically rewrite big parts of your program after even very simple changes. Disagree. Readability is opinionated so I won't address that but this is an example of functional: gg = (x) => x * x * x y = 1 a = (x) => x + 1 b = (x) => x * 2 c = (x) => x * x d = (x) => x - 4 f = a . b . c . d result = f(y) OOP example: class Domain1 constructor(n: int) this.x = n def gg() this.x *= this.x * this.x def getX() -> int return this.x class Domain2: constructor(n: int) this.x = n def a: this.x += 1 def b: this.x *= 2 def c: this.x *= this.x def d: this.x -= 4 def f: this.a() this.b() this.c() this.d() def getX() -> int return this.x state = Domain(1) state.f() result = state.getX() What if realize d and a fits better in Domain1 and I want to compose d and a with gg in the OOP program? I have to refactor Domain2 and Domain1. Or I create a Domain3 that includes a Domain1 and a Domain2 How do I do it in functional programming? domain3 = gg . d . a #Note I use the fucntion composition operator which means: a . b = (x) => b(a(x)) or a . b . c = (x) => c(b(a(x))) Functions by nature with the right types are composable without modification. A can compose with B without A knowing about B or vice versa. The same cannot be said for objects. Try achieving the same goal with OOP.... It will be a mess of instantiating state and objects within objects and refactoring your classes. OOP is NOT modular. It's pretty clear. One style is more modular than the other. Objects tie methods to state such that the methods are tied to each other and can't be composed without instantiating state or doing complex Object compositions and rewriting the Objects themselves. In programming you want legos. You want legos to compose. You don't want legos that don't fit such that you have to break the legos or glue them together. >Imperative (and OO) programming idiomatically let you do a bigger mess with side effects, and you know less about the data dependencies just from looking at the function specifications - but it also allows you to do exploratory programming much faster (no need to pass a new argument down 20 levels of your call stack when some code deep down suddenly requires a new argument). And it allows you to modify the behaviour locally without refactoring the whole thing constantly. you shouldn't be programming with state ever if you're doing FP. You need to segregate state away from your program as much as possible. State by nature is hard to modularize. State should be very simple generic mutation operations like getValue and setValue, it should rarely ever contain operational logic.
- DeathArrow 2y ago> And here’s the kicker. All of these functions did the same thing as the method. My only question is if you have function x, y and z, how do you restrict function z so it can only be called from function x, but not from function y? If you have classes you can use access modifiers.
- freilanzer 2y agoWhy do you want that if there is no state involved?
- ninetyninenine 2y agoExactly. These functions are stateless and thus calling the functions ultimately doesn’t really do anything.
- DeathArrow 2y agoI wasn't referring to a pure functional context. I was thinking of a context where you have functions and procedures but no objects.
- freilanzer 2y agoYou can still have modules, for example. They're a way of grouping functions and types.
- ninetyninenine 2y agoYou don’t need to restrict functions. You can still organize functions into groups via libraries or modules. But ultimately that’s just aesthetics. ModulaA.funcA ModuleB.funcB FuncA cannot be called from ModuleB. This restriction is possible in terms of organizing code but you can see it’s just naming and ultimately has no effect outside of aesthetic appeal.