Any suggestions on: how/where to start? which book to refer?
A program can be modelled as a set of communicating black-box objects, with their own state.
The idea is to separate concerns, abstracting away implementation behind well-defined interfaces, which can in turn be implemented by other objects to cleanly replace parts of the application.
The rest of OO is pretty much just understanding Design Patterns (a set of names for common interactions between objects, and methods for setting these interactions up), grokking inheritance, and the difference between inheritance and composition, and grasping how to design a good OO system (how thickly to layer your classes, how much abstraction and what sorts, etc.)
The best languages for learning OO are Ruby and Smalltalk.
Getters and setters only really work in programming languages with good metaprogramming support. In Java and Objective-C, they're ungainly and awkward. In Smalltalk and Ruby, they just kind of happen.
I strongly recommend three books:
Smalltalk, Objects, and Design - by Chamond Liu
Object Thinking, by David West
Object Design: Roles, Responsibilities, and Collaborations by Rebecca Wirfs-Brock
As for the idea of a set of common patterns that can be reused in a variety of situations, yes, that's a natural consequence of OO. But that's a natural consequence of any paradigm. OO's just had better marketing and GoF gave them a name.
In any case, you can write OO in any language. Heck, if you look into the history, Scheme, A multiparadigm language in the Lisp family typically associated with FP, was actually intended to be something approximating OO (it was designed to implement Carl Hewitt's Actor Model, so as to help Sussman and Steele understand it better. They subsequently realized that their code for creating actors and sending messages was identical to their code for instantiating and calling functions, leading them to generalize and only include lambda in the language, concluding that actors and functions were one and the same. Hewitt did not approve).
One of the authors is teaching a two-part MOOC on edx over the material [1] (how much of it, I don't know).
[0] https://mitpress.mit.edu/books/concepts-techniques-and-model...
[1] https://www.edx.org/course/paradigms-computer-programming-lo...!
OOP at it's core is about answering the question "Where the fuck do we put our code?"[0].
Imagine it's the long ago and year is of 1 B.O.(before OOP). Your language has primitive types and functions. You maintain a large line of business application. Someone has just invented the apartment building so you are given the task that to make sure your application handles apartment units correctly. You go through and find all of your functions that take parameters like "int streetNumber, string street, int zipcode,string city", and you add apartment number to them getting "int streetNumber, string street, string apartment, int zipcode,string city". Having these 5 parameters that you pass into all the same functions is super painful. It's also error prone to edit.
So you decide there has to be be a better way and decide to create structs. You decide to group these 5 parameters together into struct(which you just invented) called mailingAddress. This is really great because you have organized these 5 parameters into one object, so mailing address is now 1 parameter instead of 5. And if you need to add or change one of these parameters there is only one place to change it. You won't accidentally forget to add apartment to some function because as soon as you add a mailing address parameter it comes with an apartment baked in. But unfortunately you still have to hunt down every function that is scattered around your goliath project to find what functions modify this mailing address. You have an itch that this could be done better. You lock yourself in your closet and go into a deep meditation for 3 days.
You come out decide there is a better way and you create classes. You decide that you'll group all of these functions that modify and interact with mailing address and put them in the same file with your struct and call it a class. This is great because in the future when you want change how the mailing address(which is something that your stake holders cares about which we refer to as the domain) works you know exactly which file to go to.
It really is that simple. 80% of OOP is just making sure you group the right code together in a way that you can find and change the code when a stakeholder asks you to. There is much more advanced OOP foo, and for that I would ironically suggest https://fsharpforfunandprofit.com/series/designing-with-type... which will blow your mind when you're ready.
[0] - yes of course it can be get more complex in terms of typing/ encapsulation/inheritance/polymorphism. [1] - I know this is simplistic because functions are data.
As for your explantation, that's technically true, but that's a very dangerous way to think about OO. OO is about treating objects as collaborating, independant entities, and if you view objects or classes as just, "a place to put your code," you'll run into trouble when you have to start thinking about objects as, well, objects.
Actually, by the Alan Kay definition, Java isn't even really OO at all. It just kind of looks like OO. You can apply OO techniques to it, but it's better to learn real OO than the bastardized version that's taught to Java programmers.
The main compliment I'd suggest to this approach is Eric Evans' book Domain-Driven Design: https://www.amazon.com/Domain-Driven-Design-Tackling-Complex...
In a bottom-up approach, you can often break things down in a variety of ways. But the most stable/useful ways are often the ones that align with the conceptual model of the domain. If I notice that certain data and behavior goes together with incoming money, I might call that an InboundMoneyWorkingUnit. But if I talk to people who've spent years working in the domain, I'll realize the object should be called Payment, and their description of what a Payment does will inform my hunt for other objects and methods.
If you come from a procedural programming in a low-level language like C, for example, there is an excellent book "Object Oriented C", which teaches you OO concepts by implementing them in C.
If you do GUI programming in a procedural language (again, mostly C) you could download Pharo and go through "Pharo by Example".
These are just examples - there are much more languages/books combos out there.
This talk is such an amazing example of clear thinking:
This is the book I wish I had 25 years ago.
I found Bruce Eckel's "Thinking In Java" useful back in day to learn OO programming and concepts. Much of what you learn is transferable to other languages.
The classic OOP examples ("This class is a car, this Mercedes class inherits from the car class, it also has a method to move, and this Mercedes object is an instance of a Mercedes") are pretty easy to grasp for a person of normal intelligence. The frustration is to then apply this when you are stuck thinking in a procedural or functional model. However once you have learned for example how to handle a database connection, you start to apply that on your own and when a similar problem comes along, you start to notice patterns: "This is really similar to the db object, I know I did right, because I just copied the concept, so I will do this in a similar way." After that learning the design patterns is quite easy, too. But at first knowing what - in this example a - singleton is does not get you anywhere, because generally you do not know how to start.
Java Interfaces are in fact an example of inheritance. Moreover, they are an example of "non OOP inheritance": it's an inheritance of type checking that actually doesn't bring any attributes to an object. It exists in support of compiler diagnostics and compile-time optimization of dispatch.
In some languages (even ones that do support inheritance very well) objects of different types can be substitutable over a common set of functions without any explicit inheritance of interfaces or anything.
We can make a Dog and Cat class in complete isolation from each other, with no common dependency, and give them a speak() method. Then pass an instance of either class to some function which just calls arg.speak(). This produces "bark!" if arg is a Dog, or "meow!" if it is a Cat.
A Java-style interface just makes this dispatch easier to optimize via a static type system, and to implement checks. The function cannot call arg.speak() unless arg is a reference to an ICanSpeak type. That is assured externally because code which passes anything else to that function will not compile. Thus Dog and Cat must inherit this ICanSpeak, which causes their instances to be eligible as arguments to that function. When they implement speak(), their implementation is type-checked against ICanSpeak's speak(): to have the right number of properly typed arguments.
Think of something you want to build, then build it. Learn the language as you go along. Pick whichever language seems like a good choice for your particular project (based on popular opinion). Learning OOP and how to build applications in one language transfers to other languages without much effort.
You also learn how to break down projects to simple tasks with this. If you want to build Facebook, first you need to have a simple HTML file. Then it needs to be served by Apache/Nginx. Then it needs JavaScript for UI behavior, then it needs a back-end framework for routing requests, then it needs a database for data persistence. Most projects can be broken down like this to make learning not the equivalent of drinking from a fire hose.
Very oversimplified, but that is what it is. See the pieces that you are playing with, and they can receive messages asking them to do something, this will be method calling. This describes objects and message passing.
Sometimes different parts need to respond to the same message, think on a car: push pedal, it means to release gas into the engine to the gas pedal, but it means squeeze the wheels to the brake pedal. Welcome to polymorphism.
And when I press a pedal I don;t need to know how it accomplish what I am asking to do. In a gas engine means releasing more gas, but in a tesla it means reducing resistance between the batteries and the motors. That would be encapsulation.
And by the way, think also in the instrument panel, they don't go asking then engine "what are you doing now", instead they just display whatever information the engine is volunteering. The engine makes a little wire spin, and the speedometer shows the speed. That would be the bases for the observable pattern. There are others, but this one helps abstract the engine it self from the car body. In other words, the UI should be nothing but one example on how a user can interact with the engine, for this you need to build your engine without thinking in ui. This would be how to structure an oo app.
As with every tool you need to know how and when to use it, but it can be quite effective if done right.
The issue with OOP is that as soon as you introduce inheritance, and things like virtual functions, you’re introducing variable program behaviour based on context. And most of the time you end up having to special-case things up in the hierarchy because nothing ever goes as you envisioned it.
Structuring your code so that you have simple data and code that operates on the data means that what’s happening in the code at a particular time is always explicit, and any deviations based on objects the code operates on are right there in front of you, not hidden in 4 virtual function implementations in different files.
It’s all special-case code you have to write anyway, but if written in OOP fashion, the complexity of it is most of the time unclear, and it’s hard to judge what code will actually be doing just by glancing at it.
One thing you should not bother doing is to order giant piles of paper just so that you can say you read X famous author on OOP or Design Patterns or whatever. That is a waste of time and money now that we have Google and blogs/online articles etc. And anyway you are going to learn by doing it for X years or months, not by reading a book.
Also, be careful because people will to make it seem much more complicated than it is. The more complex or subtle aspects you are probably only going to remember or understand if you learn them through practice anyway.
https://www.amazon.com/Introduction-Object-Oriented-Programm...
It's going to be difficult to find excellent OO resources for every conceivable language and stack.
https://en.wikipedia.org/wiki/Design_Patterns
https://www.amazon.com/Smalltalk-Best-Practice-Patterns-Kent...
I also suggest you drop everything in Amazon links that isn't necessary, which is most of it. I rarely click on a link without looking to see where it goes, and Amazon links are particularly suspicious because the affiliate program gives people a financial motive to get link clicks.
- Understand how all programs can be written as lists of lists of lists... and so on
- Pick up the language that you work in. Identify what construct of that language allows you to approximate scheme/lisp lists. For me this is objects in java & php, and functions in javascript
- Code your program as a list of lists of lists... in the language of your choice.
- Congrats, you got OOP
And SICP talks about a lot more than any particular constructs. Its the sort of book you can come back to, and take what you need to go further.
2. Working OOP, which you can learn in an afternoon from a handful of blog posts and/or library examples.
That's the fellow who invented UML, and wrote the foreword to the GoF Design Patterns Book. https://en.wikipedia.org/wiki/Grady_Booch
[1] "CS 108 Object Oriented System Design":
I don't think I'll ever work in a purely functional language, but I still took an online course to learn something about functional approaches. It was great; it has definitely changed how I program for the better.
Overall though they were often used by default where there were better ways and just as often abused to allow a ton of shared state (globals in disguise), which almost always makes code harder to follow.
That would be the best way.
Names would be: Dijkstra, Parnas, Kay, Booch, and many others. Once you assemble a nice collection of notes, links and questions, you'll be allright and will never fall for "OO is A, B and C!" oversimplified nonsense many books attempt to sell.
Do not believe any comment in this thread either, rather take things with a (huge) grain of salt -- remember, we're dealing with a Holy Grail here, and everyone interested is quite opinionated :)