views:

1039

answers:

12

By putting functionality into a function, does that alone constitute an example of encapsulation or do you need to use objects to have encapsulation?

I'm trying to understand the concept of encapsulation. What I thought was if I go from something like this:

n = n + 1

which is executed out in the wild as part of a big body of code and then I take that, and put it in a function such as this one, then I have encapsulated that addition logic in a method:

addOne(n)
    n = n + 1
    return n

Or is it more the case that it is only encapsulation if I am hiding the details of addOne from the outside world - like if it is an object method and I use an access modifier of private/protected?

+1  A: 

It's a component-level thing

Check this out:

In computer science, Encapsulation is the hiding of the internal mechanisms and data structures of a software component behind a defined interface, in such a way that users of the component (other pieces of software) only need to know what the component does, and cannot make themselves dependent on the details of how it does it. The purpose is to achieve potential for change: the internal mechanisms of the component can be improved without impact on other components, or the component can be replaced with a different one that supports the same public interface.

(I don't quite understand your question, let me know if that link doesn't cover your doubts)

Juan Manuel
A: 

It's not normally very meaningful to speak of encapsulation without reference to properties rather than solely methods -- you can put access controls on methods, certainly, but it's difficult to see how that's going to be other than nonsensical without any data scoped to the encapsulated. Probably you could make some argument validating it, but I suspect it would be tortuous.

So no, you're most likely not using encapsulation just because you put a method in a class rather than having it as a global function.

chaos
+1  A: 

The abstract concept of encapsulation means that you hide implementation details. Object-orientation is but one example of the use of ecnapsulation. Another example is the language called module-2 that uses (or used) implementation modules and definition modules. The definition modules hid the actual implementation and therefore provided encapsulation.

Encapsulation is used when you can consider something a black box. Objects are a black box. You know the methods they provide, but not how they are implemented.

[EDIT] As for the example in the updated question: it depends on how narrow or broad you define encapsulation. Your AddOne example does not hide anything I believe. It would be information hiding/encapsulation if your variable would be an array index and you would call your method moveNext and maybe have another function setValue and getValue. This would allow people (together maybe with some other functions) to navigate your structure and setting and getting variables with them being aware of you using an array. If you programming language would support other or richer concepts you could change the implementation of moveNext, setValue and getValue with changing the meaning and the interface. To me that is encapsulation.

Jeroen Huinink
I updated my question to clarify the ambiguity (hopefully).
+10  A: 

I will be the first to disagree with what seems to be the answer trend. Yes, a function encapsulates some amount of implementation. You don't need an object (which I think you use to mean a class).

See Meyers too.

alphadogg
I would've figured the answer is obviously yes. When calling a function, you shouldn't worry about how the function is doing the job.
toast
Agreed. Seems obvious to me too. Some people just get hung up on what their OOP textbook said. Going back to the definition, that encapsulation hides implementation details so the user don't have to worry about them, a function is obviously an example of encapsulation.
jalf
Right. The thing is, can you change the implementation w/o affecting code using the implementation? If so, that behavior (what that code does) is encapsulated.
alphadogg
I like the Meyers article - it also serves as an explanation of C# extension methods. Lots of concepts in OO are in fact generally applicable, e.g. overrideable (virtual) methods are like named parameters with default values - the values being functions of course.
Daniel Earwicker
In general I agree that functions can provide some encapsulation, but the encapsulation is often broken by side effects. In C, for example, functions still provide some abstraction, but details of how the function works (side effects) are often quite important.
Moses Schwartz
+4  A: 

A method is no more an example of encapsulation than a car is an example of good driving. Encapsulation isn't about the synax, it is a logical design issue. Both objects and methods can exhibit good and bad encapsulation.

The simplest way to think about it is whether the code hides/abstracts the details from other parts of the code that don't have a need to know/care about the implementation.

Going back to the car example: Automatic transmission offers good encapsulation: As a driver you care about forward/back and speed. Manual Transmission is bad encapsulation: From the driver's perspective the specific gear required for low/high speeds is generally irrelevant to the intent of the driver.

JohnFx
Got it. The transmission example is very clear. Thank you.
+3  A: 

No, objects aren't required for encapsulation. In the very broadest sense, "encapsulation" just means "hiding the details from view" and in that regard a method is encapsulating its implementation details.

That doesn't really mean you can go out and say your code is well-designed just because you divided it up into methods, though. A program consisting of 500 public methods isn't much better than that same program implemented in one 1000-line method.

In building a program, regardless of whether you're using object oriented techniques or not, you need to think about encapsulation at many different places: hiding the implementation details of a method, hiding data from code that doesn't need to know about it, simplifying interfaces to modules, etc.

Update: To answer your updated question, both "putting code in a method" and "using an access modifier" are different ways of encapsulating logic, but each one acts at a different level.

Putting code in a method hides the individual lines of code that make up that method so that callers don't need to care about what those lines are; they only worry about the signature of the method.

Flagging a method on a class as (say) "private" hides that method so that a consumer of the class doesn't need to worry about it; they only worry about the public methods (or properties) of your class.

John Price
You also can't say your code is well-designed just because you divided it up into classes, either ;)
Mo Flanagan
@Mo oh, certainly. My point was that if you're picking encapsulation along a single axis or at a single level of abstraction and then saying "well, guess my program's encapsulated", you're doing it wrong.
John Price
+4  A: 

Sure it is.

For example, a method that operates only on its parameters would be considered "better encapsulated" than a method that operates on global static data.

Encapsulation has been around long before OOP :)

Mo Flanagan
+8  A: 

Perhaps you are confusing abstraction with encapsulation, which is understood in the broader context of object orientation.

Encapsulation properly includes all three of the following:

  • Abstraction
  • Implementation Hiding
  • Division of Responsibility

Abstraction is only one component of encapsulation. In your example you have abstracted the adding functionality from the main body of code in which it once resided. You do this by identifying some commonality in the code - recognizing a concept (addition) over a specific case (adding the number one to the variable n). Because of this ability, abstraction makes an encapsulated component - a method or an object - reusable.

Equally important to the notion of encapsulation is the idea of implementation hiding. This is why encapsulation is discussed in the arena of object orientation. Implementation hiding protects an object from its users and vice versa. In OO, you do this by presenting an interface of public methods to the users of your object, while the implementation of the object takes place inside private methods.

This serves two benefits. First, by limiting access to your object, you avoid a situation where users of the object can leave the object in an invalid state. Second, from the user's perspective, when they use your object they are only loosely coupled to it - if you change your implementation later on, they are not impacted.

Finally, division of responsility - in the broader context of an OO design - is something that must be considered to address encapsulation properly. It's no use encapsulating a random collection of functions - responsibility needs to be cleanly and logically defined so that there is as little overlap or ambiguity as possible. For example, if we have a Toilet object we will want to wall off its domain of responsibilities from our Kitchen object.

In a limited sense, though, you are correct that a function, let's say, 'modularizes' some functionality by abstracting it. But, as I've said, 'encapsulation' as a term is understood in the broader context of object orientation to apply to a form of modularization that meets the three criteria listed above.

Serx
If the function was called "AddX" where X is a value that currently has a value of 1 but this may change, then there would be information hiding. The specific value being added would be hidden in the function definition.
Daniel Earwicker
Also, functions definitely divide up responsibility. Each function takes responsibility for something that other functions don't do. Yes, a given set of functions may be poorly designed so they overlap, but then the same is true of a poorly designed set of classes.
Daniel Earwicker
@Serx The function addOne expresses "what" it does and hides "how" it does it. So this would qualify as abstraction + information hiding. Why are you so focused on objects? And as Earwicker states, functions can divide up responsibility, but I find this a rather vague criterion for encapsulation.
eljenso
@eljenso: The OP "is trying to understand the concept of encapsulation". Regardless the vagaries of the linguistic definition, the term encapsulation is in a sense a reserved keyword in the field of object orientation with a specific meaning already defined. I'm simply trying to clarify that meaning
Serx
@Serx - that's correct. i was looking for the common understanding of the term. didn't really want to open up a big computer science debate. i think you covered it pretty thoroughly. thanks.
@Serx - as long as you understand why the standard meaning is useless, then we're all on the same page. :)
Daniel Earwicker
addOne perfectly hides how exactly it adds one; consider addOne(n){/*dear Lord, please make m=n+1, thanks*/return m;} if it works - it is another way to add one. since you don't care which one is used - this is hidden from you
Pavel Feldman
Abstraction is not a component of encapsulation; abstraction works alongside encapsulation. Encapsulation hides implementation complexity. The addOne(n) function encapsulates addition, but does not abstract it. What would be an abstraction is addSome(n,m) taking addOne(), addTwo() to a simpler form.
alphadogg
+1  A: 

Let's simplify this somewhat with an analogy: you turn the key of your car and it starts up. You know that there's more to it than just the key, but you don't have to know what is going on in there. To you, key turn = motor start. The interface of the key (that is, e.g., the function call) hides the implementation of the starter motor spinning the engine, etc... (the implementation). That's encapsulation. You're spared from having to know what's going on under the hood, and you're happy for it.

If you created an artificial hand, say, to turn the key for you, that's not encapsulation. You're turning the key with additional middleman cruft without hiding anything. That's what your example reminds me of - it's not encapsulating implementation details, even though both are accomplished through function calls. In this example, anyone picking up your code will not thank you for it. They will, in fact, be more likely to club you with your artificial hand.

Any method you can think of to hide information (classes, functions, dynamic libraries, macros) can be used for encapsulation.

Matt
I like your motor example but you lost me with your humorous artificial hand example.
Kenneth Johns
A: 

The Reference Model of Open Distributed Processing - written by the International Organisation for Standardization - defines the following concepts:

Entity: Any concrete or abstract thing of interest.

Object: A model of an entity. An object is characterised by its behaviour and, dually, by its state.

Behaviour (of an object): A collection of actions with a set of constraints on when they may occur.

Interface: An abstraction of the behaviour of an object that consists of a subset of the interactions of that object together with a set of constraints on when they may occur.

Encapsulation: the property that the information contained in an object is accessible only through interactions at the interfaces supported by the object.

These, you will appreciate, are quite broad. Let us see, however, whether putting functionality within a function can logically be considered to constitute towards encapsulation in these terms.

Firstly, a function is clearly a model of a, 'Thing of interest,' in that it represents an algorithm you (presumably) desire executed and that algorithm pertains to some problem you are trying to solve (and thus is a model of it).

Does a function have behaviour? It certainly does: it contains a collection of actions (which could be any number of executable statements) that are executed under the constraint that the function must be called from somewhere before it can execute. A function may not spontaneously be called at any time, without causal factor. Sounds like legalese? You betcha. But let's plough on, nonetheless.

Does a function have an interface? It certainly does: it has a name and a collection of formal parameters, which in turn map to the executable statements contained in the function in that, once a function is called, the name and parameter list are understood to uniquely identify the collection of executable statements to be run without the calling party's specifying those actual statements.

Does a function have the property that the information contained in the function is accessible only through interactions at the interfaces supported by the object? Hmm, well, it can.

As some information is accessible via its interface, some information must be hidden and inaccessible within the function. (The property such information exhibits is called information hiding, which Parnas defined by arguing that modules should be designed to hide both difficult decisions and decisions that are likely to change.) So what information is hidden within a function?

To see this, we should first consider scale. It's easy to claim that, for example, Java classes can be encapsulated within a package: some of the classes will be public (and hence be the package's interface) and some will be package-private (and hence information-hidden within the package). In encapsulation theory, the classes form nodes and the packages form encapsulated regions, with the entirety forming an encapsulated graph; the graph of classes and packages is called the third graph.

It's also easy to claim that functions (or methods) themselves are encapsulated within classes. Again, some functions will be public (and hence be part of the class's interface) and some will be private (and hence information-hidden within the class). The graph of functions and classes is called the second graph.

Now we come to functions. If functions are to be a means of encapsulation themselves they they should contain some information public to other functions and some information that's information-hidden within the function. What could this information be?

One candidate is given to us by McCabe. In his landmark paper on cyclomatic complexity, Thomas McCabe describes source code where, 'Each node in the graph corresponds to a block of code in the program where the flow is sequential and the arcs correspond to branches taken in the program.'

Let us take the McCabian block of sequential execution as the unit of information that may be encapsulated within a function. As the first block within the function is always the first and only guaranteed block to be executed, we can consider the first block to be public, in that it may be called by other functions. All the other blocks within the function, however, cannot be called by other functions (except in languages that allow jumping into functions mid-flow) and so these blocks may be considered information-hidden within the function.

Taking these (perhaps slightly tenuous) definitions, then we may say yes: putting functionality within a function does constitute to encapsulation. The encapsulation of blocks within functions is the first graph.

There is a caveate, however. Would you consider a package whose every class was public to be encapsulated? According to the definitions above, it does pass the test, as you can say that the interface to the package (i.e., all the public classes) do indeed offer a subset of the package's behaviour to other packages. But the subset in this case is the entire package's behaviour, as no classes are information-hidden. So despite regorously satisfying the above definitions, we feel that it does not satisfy the spirit of the definitions, as surely something must be information-hidden for true encapsulation to be claimed.

The same is true for the exampe you give. We can certainly consider n = n + 1 to be a single McCabian block, as it (and the return statement) are a single, sequential flow of executions. But the function into which you put this thus contains only one block, and that block is the only public block of the function, and therefore there are no information-hidden blocks within your proposed function. So it may satisfy the definition of encapsulation, but I would say that it does not satisfy the spirit.

All this, of course, is academic unless you can prove a benefit such encapsulation.

There are two forces that motivate encapsulation: the semantic and the logical.

Semantic encapsulation merely means encapsulation based on the meaning of the nodes (to use the general term) encapsulated. So if I tell you that I have two packages, one called, 'animal,' and one called 'mineral,' and then give you three classes Dog, Cat and Goat and ask into which packages these classes should be encapsulated, then, given no other information, you would be perfectly right to claim that the semantics of the system would suggest that the three classes be encapsulated within the, 'animal,' package, rather than the, 'mineral.'

The other motivation for encapsulation, however, is logic.

The configuration of a system is the precise and exhaustive identification of each node of the system and the encapsulated region in which it resides; a particular configuration of a Java system is - at the third graph - to identify all the classes of the system and specify the package in which each class resides.

To logically encapsulate a system means to identify some mathematical property of the system that depends on its configuration and then to configure that system so that the property is mathematically minimised.

Encapsulation theory proposes that all encapsulated graphs express a maximum potential number of edges (MPE). In a Java system of classes and packages, for example, the MPE is the maximum potential number of source code dependencies that can exist between all the classes of that system. Two classes within the same package cannot be information-hidden from one another and so both may potentially form depdencies on one another. Two package-private classes in separate packages, however, may not form dependencies on one another.

Encapsulation theory tells us how many packages we should have for a given number of classes so that the MPE is minimised. This can be useful because the weak form of the Principle of Burden states that the maximum potential burden of transforming a collection of entities is a function of the maximum potential number of entities transformed - in other words, the more potential source code dependencies you have between your classes, the greater the potential cost of doing any particular update. Minimising the MPE thus minimises the maximum potential cost of updates.

Given n classes and a requirement of p public classes per package, encapsulation theory shows that the number of packages, r, we should have to minimise the MPE is given by the equation: r = sqrt(n/p).

This also applies to the number of functions you should have, given the total number, n, of McCabian blocks in your system. Functions always have just one public block, as we mentioned above, and so the equation for the number of functions, r, to have in your system simplifies to: r = sqrt(n).

Admittedly, few considered the total number of blocks in their system when practicing encapsulation, but it's readily done at the class/package level. And besides, minimising MPE is almost entirely entuitive: it's done by minimising the number of public classes and trying to uniformly distribute classes over packages (or at least avoid have most packages with, say, 30 classes, and one monster pacakge with 500 classes, in which case the internal MPE of the latter can easily overwhelm the MPE of all the others).

Encapsulation thus involves striking a balance between the semantic and the logical.

All great fun.

A: 

in strict object-oriented terminology, one might be tempted to say no, a "mere" function is not sufficiently powerful to be called encapsulation...but in the real world the obvious answer is "yes, a function encapsulates some code".

for the OO purists who bristle at this blasphemy, consider a static anonymous class with no state and a single method; if the AddOne() function is not encapsulation, then neither is this class!

and just to be pedantic, encapsulation is a form of abstraction, not vice-versa. ;-)

Steven A. Lowe
+1  A: 

Encapsulation is a process in which attributes(data member) and behavior(member function) of a objects in combined together as a single entity refer as class.

Manoj Kumar Singh