If I may piggyback off your comment, I'll also throw my two cents in that mostly apply to Java:
1. A class may only ever mutate itself. Never anyone else. So if your Foo class has a method that accepts a Bar as input, you must NOT change that Bar. You may return a new instance of a Bar with different values.
2. Don't use class inheritance unless you are forced to at gunpoint or by a framework you're forced to use.
3. True OOP classes will probably have a deep nesting of dependencies. I.e, a Foo class has a Bar field, which has a Baz field, etc. However, those dependencies should be VERTICAL. Do NOT keep references to other classes that your class does not "own". This creates cyclical dependencies and tight coupling. Most likely somebody else should own both objects at a higher level.
4. If your class has a method that doesn't depend on the object's current state, make it static. (This, with the other points, also hints that the method should not have side effects. Static methods should be pure functions)
5. Each package probably has one public class that actually does stuff. This is your domain model and represents a "workflow" (e.g., managing a user account: create, change profile picture, delete, etc). Any other public types from the package should only be plain old data used by the methods of your domain model.
All that said, I still don't think that OOP is actually the best way to solve most problems.
I wrote C/C++, no BOOST, in 100K LOC size systems, using OOP with simplified rules similar to this; works well for me