Structs and functions are great if you see yourself adding more new functions than data types in the future (the existing functions don't need to change!). OOP is great if you see yourself adding more data types (the existing classes don't need to change!).
You're gonna have to justify that. Can't just take your word for it. Where do you store your state, if not in objects?
OK, so in global variables, like in C language. And you think this is better than OOP. Glad that's working for you!
Even if there is some data I want to keep in memory there is no need for a global usually. In go I may just keep it in a var in a goroutine that doesn’t exit until the process does.
type Engine struct {
HorsePower int
}
func (e Engine) Start() {
fmt.Println("Engine is starting with", e.HorsePower, "horsepower.")
}Not at all!
This is the main reason OO has dominated for so long. OO has somehow taken on the meaning "Anything which isn't C".
And it's not even an accurate representation of C, it's a straw man version of C. C programmers know the perils of global variables.
Here is some code:
int myState;
void myFunc() {
}
If I take the above code and make it look like C: #ifndef MYSTUFF_H
#define MYSTUFF_H
int myState;
void myFunc() {
...
}
#endif
Yuck! Global variable! disgusting!Now I make it look like Java:
class MyStuff {
int myState;
void myFunc() {
...
}
}
This is somehow "encapsulated". But start calling myFunc() at different times from different threads and see if myState behaves more like a stack variable or a global variable.OO made it much more socially acceptable to pollute your code with this kind of "encapsulation". And OO devs decided that even this was too much of a straightjacket - some people liked C#'s take on properties, where you didn't have to work so hard writing getters and setters (further breaking encapsulation).
Real C Programmers™ actually encapsulate:
my_state_t myFunc(my_state_t in) {..}Once you take away inheritance ("prefer composition"), polymorphism (better offerings elsewhere), encapsulation (not encapsulation!), message-passing (better offerings elsewhere), you're left with a small syntactic trick that really wasn't that hard to do in C.
Even Lua gives you that [1]:
> This use of a self parameter is a central point in any object-oriented language. Most OO languages have this mechanism partly hidden from the programmer, so that she does not have to declare this parameter (although she still can use the name self or this inside a method). Lua can also hide this parameter, using the colon operator.
function Account.withdraw (self, v)
self.balance = self.balance - v
end
function Account:withdraw (v)
self.balance = self.balance - v
end
[1] https://www.lua.org/pil/16.htmlAccording to FP, data shouldnt be stored where possible and yes, if you can, store global or top level immutable blobs and pass by reference.
> That's how the real world is.
Well, maybe not. I dont rememer where it came to me that OOP is like classical physics, where everything has to get passed around with the speed of light and FP is like quantum physics, stateless until you do the computation. I dont know how accurate this analogy is but it still fascinates me since modelling reality is enlarge what programming is.
Actually all four ways are possible: with either, neither, or both.
The GoF book says to prefer composition over inheritance much of the time, in an early page of the book.
Hear me out, I don't think classes should be used to mutate state, or perform actions on their own. But they are a nice way to namespace and think about components properly. It can be achieved with just structs and functions (strongly typed, for the love of all deities) but giving a container like a class has its advantages to namespace some categories of functions belonging to their own structs.
I agree that many other uses of classes (and fucking design patterns piled on top) were, and still are, a major source of pain in software development, I'm very glad to see that a lot of folks around the 15-25 years of experience realised the footguns are not worth it and adapted to write more readable "dumb" code.
Precisely. I’m a DBRE, not SWE, but I use Python a lot, and have written some internal tooling. Classes as namespacing is wonderful.
- A type
- A name for it
- A canonical way to build a value of that type
- A consistent way to reference its semantic meaning at runtime and in any static/build time/documentation format
- A singular, easily discoverable place to change it