Update
This commit is contained in:
parent
2f23834d88
commit
3510c0d46f
15 changed files with 88 additions and 21 deletions
12
oop.md
12
oop.md
|
@ -16,11 +16,13 @@ Generally OOP programs solve problems by having **[objects](object.md)** that co
|
|||
|
||||
Now many OO languages use so called **class OOP**. In these we define object [classes](class.md), similarly to defining [data types](data_type.md). A class is a "template" for an object, it defines methods and types of data to hold. Any object we then create is then created based on some class (e.g. we create the object `alice` and `bob` of class `Human`, just as normally we create a variable `x` of type `int`). We say an object is an **instance** of a class, i.e. object is a real manifestation of what a class describes, with specific data etc.
|
||||
|
||||
The more "lightweight" type of OOP is called **classless OOP** which is usually based on having so called prototype objects instead of classes. In these languages we can simply create objects without classes and then assign them properties and methods dynamically at runtime. Here instead of creating a `Human` class we rather create a prototype object that serves as a template for other objects. To create specific humans we clone the prototype human and modify the clone.
|
||||
|
||||
OOP furthermore comes with some basic principles such as:
|
||||
|
||||
- **[encapsulation](encapsulation.md)**: Object should NOT be able to access other object's data directly -- they may only use their methods. For example an object shouldn't be able to access the `height` attribute of a `Human` object, it should be able to access it only via methods of that object such as `getHeight`. (This leads to the setter/getter antipattern).
|
||||
- **[polymorphism](polymorphism.md)**: Different objects (e.g. of different classes) may have methods with the same name which behave differently for either object and we may just call that method without caring what kind of object that is (the correct implementation gets chosen at runtime). E.g. objects of both `Human` and `Bomb` classes may have a method `setOnFire`, which with the former will kill the human and with the latter will cause an explosion killing many humans. This is good e.g. in a case when we have an array of [GUI](gui.md) components and want to perform e.g. resize on every one of them: we simply iterate over the whole array and call the method `resize` on each object without caring whether the object is a button, checkbox or a window.
|
||||
- **[inheritance](inheritance.md)**: In class OOP classes form a hierarchy in which parent classes can have child classes, e.g. a class `LivingBeing` will have `Human` and `Animal` subclasses. Subclasses inherit stuff from the parent class and may add some more. However this leads to other antipatterns such as the [diamond_problem](diamond_problem.md). Inheritance is nowadays regarded as bad even by normies and is being replaced by [composition](composition.md).
|
||||
- **[inheritance](inheritance.md)**: In class OOP classes form a [hierarchy](hierarchy.md) in which parent classes can have child classes, e.g. a class `LivingBeing` will have `Human` and `Animal` subclasses. Subclasses inherit stuff from the parent class and may add some more. However this leads to other antipatterns such as the [diamond_problem](diamond_problem.md). Inheritance is nowadays regarded as bad even by normies and is being replaced by [composition](composition.md).
|
||||
|
||||
## Why It's Shit
|
||||
|
||||
|
@ -36,20 +38,20 @@ OOP furthermore comes with some basic principles such as:
|
|||
- If you want to program in object-oriented way and have a good justification for it, **you don't need an OOP language anyway**, you can emulate all aspects of OOP in simple languages like C. So instead of building the idea into the language itself and dragging it along forever and everywhere, it would be better to have optional OOP libraries.
|
||||
- It generalizes and simplifies programming into a few rules of thumb such as encapsulation, again for the sake of inexperienced noobs. However there are no simple rules for how to program well, good programming requires a huge amount of experience and as in any art, good programmer knows when breaking the general rules is good. OOP doesn't let good programmers do this, it preaches things like "global variables bad" which is just too oversimplified and hurts good programming.
|
||||
|
||||
## But Which Paradigm To Use Instead Of OOP?
|
||||
## So Which Paradigm To Use Instead Of OOP?
|
||||
|
||||
After many people realized OOP is kind of shit, there has been a boom of "OOP alternatives" such as [functional](functional.md), [traits](traits.md), [agent oriented programming](agent_oriented_programming.md), all kinds of "lightweight" OOP etc etc. Which one to use?
|
||||
|
||||
In short: NONE, **by default use the [imperative](imperative.md) paradigm** (also called "procedural"). Remember this isn't to say you shouldn't ever apply a different paradigm, but imperative should be the default, most prevalent and suitable one to use in solving most problems. There is nothing new to invent or "beat" OOP.
|
||||
|
||||
But why imperative? Why can't we simply improve OOP or come up with something ultra genius to replace it with? Why do you say OOP is bad because it's forced and now you are forcing imperative paradigm? The answer is that the **imperative paradigm is special because it is how computers actually work**, it is not made up but rather it's the **natural low level paradigm with minimum [abstraction](abstraction.md) that reflects the underlying nature of computers**. This makes it special among all other paradigms because:
|
||||
But why imperative? Why can't we simply improve OOP or come up with something ultra genius to replace it with? Why do we say OOP is bad because it's forced and now we are forcing imperative paradigm? The answer is that the **imperative paradigm is special because it is how computers actually work**, it is not made up but rather it's the **natural low level paradigm with minimum [abstraction](abstraction.md) that reflects the underlying nature of computers**. You may say this is just bullshit arbitrary rationalization but no, these properties makes procedural paradigm special among all other paradigms because:
|
||||
|
||||
- Its implementation is simple and [suckless](suckless.md)/[LRS](lrs.md) because it maps nicely and naturally to the underlying hardware -- basically commands in a language simply translate to one or more instructions. This makes construction of compilers easy.
|
||||
- It's predictable and efficient, i.e. a programmer writing imperative code can see quite clearly how what he's writing will translate to the assembly instructions. This makes it possible to write highly efficient code, unlike high level paradigms that perform huge amounts of [magic](magic.md) for translating foreign concepts to machine instructions -- and of course this magic may differ between compilers, i.e. what's efficient code in one compiler may be inefficient in another (similar situation arose e.g. in the world of [OpenGL](opengl.md) where driver implementation started to play a huge role and which led to the creation of a more low level API [Vulkan](vulkan.md)).
|
||||
- It doesn't force high amounts of unnecessary high level abstraction. This means we MAY use any abstraction, even OOP, if we currently need it, e.g. via a [library](library.md), but we aren't FORCED to use a weird high level concepts on problems that can't be described easily in terms of those concepts. That is if you're solving a non-OOP problem with OOP, you waste effort on translating that problem to OOP and the compiler then wastes another effort on un-OOPing this to translate this to instructions. With imperative paradigm this can't happen because you're basically writing instructions which has to happen either way.
|
||||
- It is generally true that the higher the abstraction, the smaller its scope should be, so the default abstraction (paradigm) should be low level. This works e.g. in science: psychology is a high level abstraction but can only be applied to study human behavior, while quantum physics is a low level abstraction which applies to the whole universe.
|
||||
- It is generally true that the higher the abstraction, the smaller its scope of application should be, so the default abstraction (paradigm) should be low level. This works e.g. in science: psychology is a high level abstraction but can only be applied to study human behavior, while quantum physics is a low level abstraction which applies to the whole universe.
|
||||
|
||||
Once computers start fundamentally working on a different paradigm, e.g. functional, we may switch to that paradigm as the default, but until then imperative is the way to go.
|
||||
Once computers start fundamentally working on a different paradigm, e.g. functional -- which BTW might happen with new types of computers such as [quantum](quantum.md) ones -- we may switch to that paradigm as the default, but until then imperative is the way to go.
|
||||
|
||||
## History
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue