I know this is something that a lot of people do without thinking about it. So let's think about it.<p>I want to know the main reasons for making variables and functions in a class private. How is it better? What can happen if you don't do it?<p>Here are a few possible reasons that I can think of that someone could have:<p>* You have been taught to do it so you just do it without thinking.<p>* It reduces the number of files you have to search in if you want to find all uses of a member.<p>* The member is hard to understand so you want to discourage people from using it.<p>To clarify, I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.
To hide implementation details from class users. You ideally <i>only</i> want to have a documented interface and all implementation details should be opaque to class users. This can be quite tricky and usually classes will export some state, typically done through getters and setters.<p>Then one day you decide you want to aggressively refactor that class. Now you can because the interface can stay the same even though you could completely re-do the guts. Better still: all your tests will still work, as will your class documentation.
> You have been taught to do it so you just do it without thinking.<p>Ouch, that's a pretty careless reason to start with. Why does insulting your audience seem like the right first move?<p>In much of the classist (classy? You decide) code I've written, the entire reason that I've chosen to encapsulate the data into a class is that maintaining a consistent data structure requires book-keeping. The fields and methods associated with this bookkeeping are not part of the public interface, because there should never be a reason for consumers to handle that stuff directly.<p>In short: even in a project that "everybody has access to," you should still implement clean APIs. If you let everybody put hooks into everything anywhere, you get horrible hacky spaghetti code.<p>Edit: and just FYI, "private" does not mean "secure" or "secret" or "untouchable." A dedicated user can gain access to, and modify, everything.
> To clarify, I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.<p>Within reason, you should treat <i>every</i> class as a tiny library that defines an API for other people to use.<p>That allows you freedom to change things within the class without breaking other code. It also makes it easier to prevent accidental misuse of the class that can leave it in weird states that aren't supposed to happen. It allows you to reason about the intended use cases of the class and write tests for them all.
Because classes are encapsulated data plus contracts over managing the object's state. If a class does not have control of its own data, then it cannot fulfill its contracts.<p>Let's say I have a Motorcycle class with 2 Wheel members. What if in the code I assume 2 Wheels when writing the serializer? And then someone comes along, instantiates a Motorcycle and nukes a Wheel? The code will break.<p>You can make an argument that OOP is not what you want, and instead create something akin to namespaces+data, and that's fine. But OOP's thing is to create a public API, and controlled state behind it.
<i>"With a sufficient number of users of an API</i>,<p><i>it does not matter what you promise in the contract:</i><p><i>all observable behaviors of your system</i><p><i>will be depended on by somebody."</i>
Because people might throw a lot of weird things at my class and I want to make sure that no invalid values are set on those properties. I might use the property or class member later on. Let's assume my app uses stock prices and because of some issue, the price for a given equity comes through as Null. And then I don't want someone to be able to do Share.Price = API.Price.<p>I might want to have a method called SetPrice(APIPrice price) and there I do a check to see if it's a valid value as far as my code is concerned. I had a situation like this handling pricing information taken from a variety of indices but I want a calculation to still work out to something usable. Also, most business users don't understand what NULL * 3.5 would mean, but they would understand 0.0 * 3.5.<p>That's the main one off the top of my head.
The following is a public API for a Car:<p>- Steering wheel<p>- Transmission<p>- Brakes and Gas pedal<p>- Doors and Windows, etc.<p>The following is a private API for a Car:<p>- The inner workings of the engine<p>- The inner workings of the battery<p>- Smart break system, internal wiring, etc.<p>All users of the Car only care about how to drive it with as little knowledge as possible.<p>Now Mazda can do a full recall and upgrade the smart breaking systems internally but millions of drivers around the world don't have to "learn" anything new, they can happily continue using the public API.<p>It makes refactoring much easier, reduces dependency and enables duct typing (in supported languages) via message passing for objects with a common public API. You also don't have to perform shotgun surgery[0] when changing classes..<p>[0] <a href="https://refactoring.guru/smells/shotgun-surgery" rel="nofollow">https://refactoring.guru/smells/shotgun-surgery</a>
>To clarify, I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.<p>If you can see the use in access modifiers for libraries then it's not so hard to make the leap to its general usefulness.
Defining objects with clear and simple APIs is extremely valuable when working on complex software projects. As the code base inevitably grows to a point where no one knows every part of it, you want developers to be able to contribute without having intimate knowledge of everything. The value proposition is the same as for third-party libraries.
History time: In 1972, David Parnas wrote a paper about "Information Hiding," and a few years later Fred Brooks wrote <i>The Mythical Man-Month</i>, possibly the most influential book about software engineering, which largely discounted the value of information hiding. 20 years later, in an updated anniversary edition of <i>The Mythical Man-Month</i>, Brooks wrote "Parnas was right, and I was wrong about information hiding."<p>Coming from Fred Brooks, this was an enormous admission! What is this amazing "information hiding?" It is separating interface from implementation, leaving one public and the other private. It is accomplished, among other means, by marking things "private."<p>This is the one thing in 20 years that Brooks found to be valuable in increasing programmer productivity in terms of essential complexity. Marking implementation details as private reduces the essential complexity of the code.<p>By the way, in some of your comments you talk about "everyone" having access to things, as if that makes a difference. Marking things as "private" is not about closing off access to particular people. It's not a security measure. It's about reducing the complexity of a given class by ensuring that the number of access points to that class are limited. That could affect other teams, sure, but it could also affect future-you, or you-working-on-other-class.
I think that lurking behind the question is an assumption that freedom and openness is better. Freedom and openness is fine until you want to build a house. Then you actually have to put walls somewhere to hold the roof up...and then you build inner walls to hide the bathroom from the rest of the house. In building software, structure is inevitable. The rightly chosen structure will give benefits; poorly chosen structure will work against you. When I build a class, it serves a purpose to some other part of the system. The purpose it serves is understood by its public members and functions. Everything else is private. What happens if you don't do this is that the next person to read and use/modify this class isn't going to know what your intention was or all the details of how it works, so it helps to give them the benefit of some hints of structure.<p>The only time I break this rule is for data-transport type classes. For example if I serialize some object into some class X before sending it to some API. Since all those objects do is hold data, I see no point in making the members private. Many people do, I suppose out of habit; or in anticipation that maybe one day those objects will do more than hold data. I'd like to hear a good argument for making members private in data-transport type classes.
> To clarify, I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.<p>A lot of people are ignoring this part of the question. The primary usefulness of object-oriented programming is <i>scope control</i>. Dependencies kill teams, and scope control helps them survive. The more I limit the scope of something, the easier for someone else to understand it and make necessary changes.<p>Imagine a language without scope control: When people try to understand how something works and what might break it, they have to consider all possible points of entry, which becomes every variable & function in your class.<p>Java programmers often pitch fits about "getters" and "setters", insisting that every variable be private and guarded by a public method. In your context, you might find this to be kind of silly since we're mostly just moving scope control around instead of limiting it, but good luck fighting that battle (I'm not going to try). At any rate, I still would not use this kind of annoyance as an excuse to wave off scope control as nothing but bureaucratic boilerplate. It has real value when used pragmatically.
The reason is simple: to prevent objects from getting to an invalid state.<p>The set of property values of an object is its state, and you can model every possible valid state and state transition. Not every state is valid. If you allow all variables to be touched willy-nilly, you allow an object to be put into an invalid state.<p>The only variables and functions that should be public are those that cannot put an object into an invalid state.
Encapsulation is a founding principle of OOP. You should not be able to directly tool with a class' internals, but use its methods to interact with it.<p>The practical reason is that this way you have limited paths (methods) with which the inner workings of a class can be modified with, whereas if anything would be public, any other obejct would be able to change a class' status rendering debugging incredibly more complicaed.<p>This is also a part of the Open-Closed principle: "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" <a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle" rel="nofollow">https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle</a>
>I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use<p>Even within a single module of code, your public interfaces <i>are</i> "APIs". If I write a class that displays a paged interface in a popup modal, there is no relevant difference between a member of my team utilizing that class (from within the same module) and other people using it (as a library I have published). They both read the documenting comments and access the public members to achieve their goals, and both will suffer from the same confusion if there is no way to tell which members are the interface and which members are implementation details.
When I write a private class, I'm declaring to the world:
These are the methods now available, their expected inputs, and their return types.<p>Anything I do inside that class that isn't marked public is an implementation detail, and might change. Given time, likely will change! But if it's not marked public, then if you want to access something in there, you'll need to think through the implications of making it public, either a new method of by adding to an existing method.<p>If I come along later and want to change things about those methods, I can do that freely, so long as I maintain the same input types and return types.<p>Internally I can change a counter from an Int to an Long, and it doesn't matter to anybody. Internally I can change the way I'm assembling a String, and that's fine. Internally I can move the definition for an interim variable to a separate function with its own tests, and that's fine. So long as I maintain the input types and return types, all is good.<p>If the fields and methods were public, on the other hand, then other classes might be accessing them directly, and now any change has to be negotiated with all callers. The counter needs to be changed from an Int to a Long? If it's public, you'll need to make sure that no other classes anywhere are referring to that counter and expecting it to be an Int.<p>Side effects are generally unwanted, and marking things as public is making everything in an implementation a side effect.
If the exposed data is (and will always be) the same as the stored data, and the data is immutable - then you are right there is little point.<p>If the field is <i>mutable</i> then obviously you may want to keep it private to ensure some invariant, or to cache/invalidate/log something when accessed. Accessing the private data directly will circumvent that.<p>If the exposed data isn’t the same as the stored data (e.g a DateTime struct might have a field with a 32 bit Unix timestamp but only exposes year/month/day/hour…). The reason for not exposing it because you don’t want consumers to depend on it. If you changed to a 64 bit internal representation you will break any consumer who is using the private field. But if you only expose year/month/day/hour/… then you can solve your year-2038-problem by simply changing the data type. Anything exposed is depended on. Always. And here is the kicker: <i>it doesn’t matter if your consumers are other classes in the same program, or library users for a shipped api, they are users and they will (mis)use your class in any way possible</i>. In the library api case you break others’ code. In the internal code case you might get a missed cache, or a harder refactor or similar.
Suppose all fields are public, but the legal value of a field is dependent upon others. Then every time you change it you also have to include all the invariant preserving logic. This is duplication of the insane sort, totally unnecessary and gratuitous and gloriously error prone (at scale). The sane option is to make it private and have one place that checks that the input is valid and have everything make use of that.
> I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.<p>It's for the same reasons. When you write code you are always writing code that some other human will consume through an interface of sorts. Even on small three person projects two truths hold:<p>- Your project mates are other humans.<p>- Your future self is an other human.<p>By defining members as private you're announcing in code to other humans that the private members are important only to the internal implementation of the class and should not be used elsewhere. And yes, your future self with thank you for the distinction.<p>Now, you don't <i>need</i> to have private methods. In some languages, a work around is to label the methods as "private" by adding a prefix of some sort like an underscore.<p>Another more functional reason has to do with inheritance. Private methods have different behaviors in different languages when inherited.
I too had that same question in the past, and the answers I got for variables were that by using them directly was harder if in the future you wanted to change the "how things are stored" in the class. With nowadays ides it's as easy as a refactor, so not a problem I personally ever had.<p>For personal projects I do use public things where necessary, and for team programming I also use public functions, but not public variables (sonar doesn't allow it) unless you make them final, which I do.<p>The important part is "when necessary". Think that each class is like a small little library (it should be at least). There are things you want others to know and use, and other internal things you don't. Public for the first, private for the second.
This reads more like a question for Stack Overflow or <a href="https://softwareengineering.stackexchange.com/" rel="nofollow">https://softwareengineering.stackexchange.com/</a> than HN, to be honest.<p>You sound like a junior developer looking for guidance.
Not for safety, gave up on that about 20 years ago. But definitely to keep state that I don't want to get messed up by outside calls. Also just to document/signal how an interface should get used to the outside world.
As software projects grow, development really becomes an exercise in managing complexity. One of the benefits of encapsulating state and functionality into classes is to reduce the amount of coupling that can occur between components. By coupling, I mean the dependence of one component on the specific behavior or implementation details of another component.<p>There will always be some amount of coupling, but reducing it makes it much easier to reason in your mind about small sections of code. With good encapsulation, there are clear interfaces between components and it is difficult to use them incorrectly.<p>You could argue that if there are only a few or even one developer on a project, there is no harm in making everything public since everyone will just use the class "correctly". However, the "correct" way to use the class is not codified or enforced anywhere other than the minds of the developers, comments, or external documentation. All of these sources can easily fall out of sync with the actual code being written. The compiler/runtime should be used to enforce correct usage when possible. This greatly reduces the cognitive load on the developer/s since they know if the code compiles or runs without error, a whole class of bugs has already been eliminated.<p>I would argue that even if access controls were completely ineffective (they didn’t actually control access), they would still be useful as API documentation within the source code to point others and your future self to the set of variables and functions that should be used to interact with the class. There is a benefit to writing code that is itself expressive of intent without requiring additional documentation or knowledge.<p>Another reason to reduce coupling is to make it easier to re-implement a single component of the system. If the component was well encapsulated and has a clean and minimal public interface, the only restriction on the new implementation is to meet that same public interface. If the component was not well encapsulated, the new implementation may have to maintain a number of details from the previous implementation than no longer make sense just to maintain all of the unnecessary coupling that’s been created between the component and the code that uses it.
I see a class as the implementation of an interface. The "interface" part of the class should be public, while the "implementation" part of the class should be private. That way, if you ever have to refactor or change the class, you can be confident your colleagues haven't built stuff on top of the "implementation" part of the class, and that you can change whatever as long as you maintain the same interface.
A class always has an API and an internal implementation. Sometimes, it is necessary to split some of that implementation up (for, e.g., code reuse) into methods or properties that have no purpose in the API, and making those methods/properties private prevents them from becoming accidental parts of the API.<p>This applies to classes without external users, too, the same divisions between class responsibilities and implementation remains valod
To keep narrow waists between your software layers.<p>A low surface area API means clean, elegant code that is simpler to use and understand.<p>>To clarify, I'm only talking about code in the same project that everyone has access to. I'm not talking about defining an API for other people to use that don't have access to the code, like when you make a library.<p>The concept of API still applies to same codebase modules. Ditching it is the shortest path to spaghetti code.
I minimize the externally visible names even/especially when I'm the only programmer on the project.<p>I do that so that "future me" has as little to understand as possible. ("reduce the number of files to search" seems silly in a world with filename wildcards and find. Are "modern" tools less capable?)
Like alot of written code that doesn't really matter to the computer, I do it as a signal to the reader: you _shouldn't_ be messing with these variable/methods just to use the class. As often noted, someone can and will still go mess with them if they want to, but at least now it's obvious.
Changing public things means changing the API. It means having to update documentation and, in case of breaking changes, major version bumps and maybe even other communication.<p>Changing private things and nobody might ever know.<p>It's about the need to coordinate and communicate changes and avoid people relying on unspecified behavior.
Intent.<p>It says "don't call me". That might be because it might be refactored without notice, or might break the intended use of the Class.<p>Even in languages without formal class access control, there is convention for labelling something as externally unsafe. It's an important part of sharing code.
Because I'm only interested in the minimal functionality to use a class. That's it.<p>I don't care and I shouldn't care about the dependencies or statefulness. I'm interested in the before-and-after of using the class methods.
I advocate for private to avoid namespace pollution and reduce cognitive load. It reduces the size of a given namespace because simply less appears when I auto-complete.<p>It lowers cognitive load because it provides demarcation of inside vs outside.
Because they are for the use of the functions within the class/module/whatever, not for the use of functions interfacing with it. Private functions for me are mainly for DRY, not for being secret special menu items.
-To hide implementation details from users of the library. We don't want to unnecessarily expose functions
-Reduce the amount tests, as the private functions wouldn't have to be <i>explicitly</i> tested
Marking it private doesn't allow any subclasses to change the value directly and must use the get/set methods provided where you can enforce standards or format accordingly.
To enforce a public API. I separate it so that callers don't accidentally muck up the workings of the class, and it simplifies how a class can be accessed and mutated
Because if someone is reading or modifying a value where that never makes sense, it indicates a bug. Compilers and IDEs catching bugs automatically is always the ideal.
Variables should not be accessed directly outside of the object
(encapsulation principle) and thus should all be private as a general rule.<p>Then, you will probably divide up the code into a number of separate methods for better structured code. All the methods that are purely internal and not part of the public API should be private if only to enforce the public API, this is also the encapsulation principle.