Having come across the concept of immutable objects recently, I would like to know the best practices for controlling access to the state. Even though the object oriented part of my brain makes me want to cower in fear at the sight of public members, I see no technical issues with something like this:
public class Foo {
public final int x;
public final int y;
public Foo( int x, int y) {
this.x = x;
this.y = y;
}
}
I would feel more comfortable declaring the fields as private and providing getter methods for each but this seems overly complex when the state is explicitly read only.
What is the best practice for providing access to the state of an immutable object?
It depends entirely on how you're going to use the object. Public fields aren't inherently evil, it's just bad to default everything to being public. For example the java.awt.Point class makes its x and y fields public, and they aren't even final. Your example seems like a fine use of public fields, but then again you might not want to expose all of the internal fields of another immutable object. There is no catch-all rule.
I have thought the same in the past but usually end up making variables private and using getters and setters so that later on I'll still have the option of making changes to the implementation while keeping the same interface.
This did remind me of something I read recently in "Clean Code" by Robert C. Martin. In chapter 6 he gives a slightly different perspective. For example, on page 95 he states
"Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions."
And on page 100:
The quasi-encapsulation of beans seems to make some OO purists feel better but usually provides no other benefit.
Based on the code sample, the Foo class would seem to be a data structure. So based on what I understood from the discussion in Clean Code (which is more than just the two quotes I gave), the purpose of the class is to expose data, not functionality, and having getters and setters probably does not do much good.
Again, in my experience, I have usually gone ahead and used the "bean" approach of private data with getters and setters. But then again, no one ever asked me to write a book about how to write better code so maybe Martin has something to say.
If your object is of local-enough usage that you don't care about the issues of breaking API changes for it in the future, there is no need to tack getters on top of the instance variables. But this is a general subject, not specific to immutable objects.
The advantage of using getters comes from one extra layer of indirection, which may come in handy if you are designing an object which will be widely used, and whose utility will extend into unforseeable future.
Regardless of immutability, you're still exposing the implementation of this class. At some stage you'll want to change the implementation (or perhaps produce various derivations e.g. using the Point example, you may want a similar Point class using polar coordinates), and your client code is exposed to this.
The above pattern may well be useful, but I'd generally restrict it to very localised instances (e.g. passing tuples of information around - I tend to find that objects of seemingly unrelated info, however, either are bad encapsulations, or that the info is related, and my tuple transforms into a fully-fledged object)
The big thing to keep in mind is that function calls provide a universal interface. Any object can interact with other objects using function calls. All you have to do is define the right signatures, and away you go. The only catch is that you have to interact solely through these function calls, which often works well but can be clunky in some cases.
The main reason to expose state variables directly would be to be able to use primitive operators directly on these fields. When done well, this can enhance readability and convenience: for example, adding Complex numbers with +, or accessing a keyed collection with []. The benefits of this can be surprising, provided that your use of the syntax follows traditional conventions.
The catch is that operators are not a universal interface. Only a very specific set of built-in types can use them, these can only be used in the ways that the language expects, and you cannot define any new ones. And so, once you've defined your public interface using primitives, you've locked yourself into using that primitive, and only that primitive (and other things that can be easily cast to it). To use anything else, you have to dance around that primitive every time you interact with it, and that kills you from a DRY perspective: things can get very fragile very quickly.
Some languages make operators into a universal interface, but Java doesn't. This is not an indictment of Java: its designers chose deliberately not to include operator overloading, and they had good reasons to do so. Even when you're working with objects that seem to fit well with the traditional meanings of operators, making them work in a way that actually makes sense can be surprisingly nuanced, and if you don't absolutely nail it, you're going to pay for that later. It is often much easier to make a function-based interface readable and usable than to go through that process, and you often even wind up with a better result than if you'd used operators.
There were tradeoffs involved in that decision, however. There are times when an operator-based interface really does work better than a function-based one, but without operator overloading, that option just isn't available. Trying to shoehorn operators in anyway will lock you into some design decisions that you probably don't really want to be set in stone. The Java designers thought that this tradeoff was worthwhile, and they might even have been correct about that. But decisions like this don't come without some fallout, and this kind of situation is where the fallout hits.
In short, the problem isn't exposing your implementation, per se. The problem is locking yourself into that implementation.
Actually, it breaks encapsulation to expose any property of an object in any way -- every property is an implementation detail. Just because everybody does this doesn't make it right. Using accessors and mutators (getters and setters) doesn't make it any better. Rather, the CQRS patterns should be used to maintain encapsulation.
I know only one prop to have getters for final properties. It is the case when you'd like to have access to the properties over an interface.
public interface Point {
int getX();
int getY();
}
public class Foo implements Point {...}
public class Foo2 implements Point {...}
Otherwise the public final fields are OK.
The class that you have developed, should be fine in its current incarnation. The issues usually come in play when somebody tries to change this class or inherit from it.
For example, after seeing above code, somebody thinks of adding another member variable instance of class Bar.
public class Foo {
public final int x;
public final int y;
public final Bar z;
public Foo( int x, int y, Bar z) {
this.x = x;
this.y = y;
}
}
public class Bar {
public int age; //Oops this is not final, may be a mistake but still
public Bar(int age) {
this.age = age;
}
}
In above code, the instance of Bar cannot be changed but externally, anybody can update the value of Bar.age.
The best practice is to mark all fields as private, have getters for the fields. If you are returning an object or collection, make sure to return unmodifiable version.
Immunatability is essential for concurrent programming.
An object with public final fields that get loaded from public constructor parameters effectively portrays itself as being a simple data holder. While such data holders aren't particularly "OOP-ish", they are useful for allowing a single field, variable, parameter, or return value to encapsulate multiple values. If the purpose of a type is to serve as a simple means of gluing a few values together, such a data holder is often the best representation in a framework without real value types.
Consider the question of what you would like to have happen if some method Foo wants to give a caller a Point3d which encapsulates "X=5, Y=23, Z=57", and it happens to have a reference to a Point3d where X=5, Y=23, and Z=57. If the thing Foo has is known to be a simple immutable data holder, then Foo should simply give the caller a reference to it. If, however, it might be something else (e.g. it might contain additional information beyond X, Y, and Z), then Foo should create a new simple data holder containing "X=5, Y=23, Z=57" and give the caller a reference to that.
Having Point3d be sealed and expose its contents as public final fields will imply that methods like Foo may assume it's a simple immutable data holder and may safely share references to instances of it. If code exists that make such assumptions, it may be difficult or impossible to change Point3d to be anything other than a simple immutable data holder without breaking such code. On the other hand, code which assumes Point3d is a simple immutable data holder can be much simpler and more efficient than code which has to deal with the possibility of it being something else.
You see this style a lot in Scala, but there is a crucial difference between these languages: Scala follows the Uniform Access Principle, but Java doesn't. That means your design is fine as long as your class doesn't change, but it can break in several ways when you need to adapt your functionality:
you need to extract an interface or super class (e.g. your class represents complex numbers, and you want to have a sibling class with polar coordinate representation, too)
you need to inherit from your class, and information becomes redundant (e.g. x can be calculated from additional data of the sub-class)
you need to test for constraints (e.g. x must be non-negative for some reason)
Also note that you can't use this style for mutable members (like the infamous java.util.Date). Only with getters you have a chance to make a defensive copy, or to change representation (e.g. storing the Date information as long)
I use a lot constructions very similar to the one you put in the question, sometimes there are things that can be better modeled with a (sometimes inmutable) data-strcuture than with a class.
All depends, if you are modeling an object, an object its defined by its behaviors, in this case never expose internal properties. Other times you are modeling a data-structure, and java has no special construct for data-structures, its fine to use a class and make public all the properties, and if you want immutability final and public off course.
For example, robert martin has one chapter about this in the great book Clean Code, a must read in my opinion.
In cases where the only purpose is to couple two values to each other under a meaningful name, you may even consider to skip defining any constructors and keep the elements changeable:
public class Sculpture {
public int weight = 0;
public int price = 0;
}
This has the advantage, to minimize the risk to confuse the parameter order when instantiating the class. The restricted changeability, if needed, can be achieved by taking the whole container under private control.
Just want to reflect reflection:
Foo foo = new Foo(0, 1); // x=0, y=1
Field fieldX = Foo.class.getField("x");
fieldX.setAccessible(true);
fieldX.set(foo, 5);
System.out.println(foo.x); // 5!
So, is Foo still immutable? :)
Related
I have just started to learn Java and is curious is it any good practice in Java for good object decomposition? Let me describe a problem. In big software project it's always a big classes like 'core' or 'ui' that tends to have a lot of methods and are intended as a mediators between smaller classes. For example, if user clicks a button on some window, this window's class sends a message to 'ui' class. This 'ui' class catches this message and acts accordingly by doing something with application user interface ( via calling method of one of it's member objects ) or by posting message to application 'core' if it's something like 'exit application' or 'start network connection'.
Such objects is very hard to break apart since they are a mere mediators between a lots of small application objects. But having a classes in application with hundreds and thousands of methods is not very handy, event if such methods are trivial task delegation from one object to another. C# solves such problem by allowing to break class implementation into multiple source files: you can divide god object any way you choose, and it will work.
Any practices by dividing such objects in Java?
One way to begin breaking such a large object apart is to first find a good subset of fields or properties managed by the large object that are related to each other and that don't interact with other fields or properties of the object. Then, create a new, smaller object using only those fields. That is, move all logic from the large class to the new smaller class. In the original large class, create a delegation method that simply passes the request along. This is a good first step that only involves changing the big object. It doesn't reduce the number of methods, but it can greatly reduce the amount of logic needed in the large class.
After a few rounds of doing this, you can begin to remove some of the delegation by pointing other objects directly at the newer, smaller objects, rather than going through the previously-huge object that was in the middle of everything.
See Wikipedia's Delegation pattern discussion for example.
As a simple example, if you have a personnel object to represent staff at a company, then you could create a payroll object to keep track of payroll-related values, a ratings object to keep track of employee ratings, an awards object to keep track of awards that the person has won, and so on.
To wit, if you started out with one big class containing the following methods, each containing business logic, among many other methods:
...
public boolean isManagement() { ... }
public boolean isExecutive() { ... }
public int getYearsOfService() { ... }
public Date getHireDate() { ... }
public int getDepartment() { ... }
public BigDecimal getBasePay() { ... }
public BigDecimal getStockShares() { ... }
public boolean hasStockSharePlan() { ... }
...
then this big object could, in its constructor, create a newly created object StaffType and a newly created object PayInformation and a newly created object StaffInformation, and initially these methods in the big object would look like:
// Newly added variables, initialized in the constructor (or as appropriate)
private final StaffType staffType;
private final StaffInformation staffInformation;
private final PayInformation payInformation;
...
public boolean isManagement() { return staffType.isManagement(); }
public boolean isExecutive() { return staffType.isExecutive(); }
public int getYearsOfService() { return staffInformation.getYearsOfService(); }
public Date getHireDate() { return staffInformation.getHireDate(); }
public int getDepartment() { return staffInformation.getDepartment(); }
public BigDecimal getBasePay() { return payInformation.getBasePay(); }
public BigDecimal getStockShares() { return payInformation.getStockShares(); }
public boolean hasStockSharePlan() { return payInformation.hasStockSharePlan(); }
...
where the full logic that used to be in the big object has been moved to these three new smaller objects. With this change, you can break the big object into smaller parts without having to touch anything that makes use of the big object. However, as you do this over time, you'll find that some clients of the big object may only need access to one of the divisible components. For these clients, instead of them using the big object and delegating to the specific object, they can make direct use of the small object. But even if this refactoring never occurs, you've improved things by separating the business logic of unrelated items into different classes.
The next logical step may be to change the BigClass into a java package. Next create new objects for each group of related functionality (noting in each class that the object is part of the new package).
The benefits of doing this are dependency reduction and performance.
No need to import the entire
package/BigClass just to get a few
methods.
Code changes to related
functionality don't require a
recompile/redeploy of the entire
package/BigClass.
Less memory used
for allocating/deallocating objects,
since you are using smaller classes.
I've seen some cases where this is solved by inheritance: let's say class Big takes care of 5 different things, and (for various reasons) they all have to be in the same class. So you pick an arbitrary inheritance order, and define:
BigPart1 // all methods dealing with topic #1
BigPart2 extends BigPart1 // all methods dealing with topic #2
...
Big extends BigPart4 // all methods dealing with the last topic.
If you can really layer things up, so that the breakage makes sense (Part2 actually uses stuff from Part1, but not vice versa, etc.) then maybe it makes some sense.
The place where I've seen this is in WebWorks, where a single class had tons of getter/setter methods -- the setters used for dependency injection (e.g., URL args passed to the object upon execution) and the getters for making values accessible to various page templates (I think it was JSPs).
So, the breakdown grouped stuff logically, e.g., assuming the class was called MyAction, there was MyActionBasicArgs (fields and setters for basic CGI arguments), extended by MyActionAdvancedArgs (advanced-option args), extended by MyActionExposedValues (getters), extended by MyActionDependencies (setters used by Spring dependency injection, non-CGI args), extended by MyAction (which contained the actual execute() method).
Because of the way dependency injection in WebWorks works (or at least, used to work, back then), it had to be one huge class, so breaking it down this way made things more maintainable. But first, please, please, see if you can simply avoid having a single huge class; think carefully about your design.
Yes, C# provides partial classes. I assume this is what you are referring to when you say:
C# solves such problem by allowing to break class implementation into multiple source
files: you can divide god object any way you choose, and it will work.
This does help make huge classes more manageable. However, I find partial classes best used when one needs to extend code created by a code generator. When a class is as large as you're talking about, it can almost always be divided into smaller classes by proper object oriented design. Using a partial class sidesteps the more correct object oriented design, which is sometimes OK as the end goal is stable, reliable, maintainable code, and not a textbook example of OO code. However, many times, putting the code of a large object into a large number of smaller partial class instances of the same class is not the ideal solution.
If you can possibly find subsets of the properties of the "god" object that do not interact with one another, then each one of those sets would logically make a good candidate for a new object type. However, if all properties of this "god" object depend on one another, then there is not much you can do to decompose the object.
I don't know why you would ever have such a large class.
I suppose if you were using a gui builder code generation and being lazy about it, you might end up in such a situation, but codegen usually ends up nasty unless you take control yourself.
Splitting a single class arbitrarily is a terrible solution to a terrible manufactured problem. (Code reuse, for one thing will become virtually impossible)
If you have to use a GUI builder, have it build smaller components, then use the small components to build up a bigger GUI. Each component should do exactly one job and do it well.
Try not to EVER edit generated code if you can avoid it. Putting business logic into a genned "frame" is just a horrid design pattern. Most code generators aren't very helpful with this, so try to just make a single, minimal edit to get at what you need from external classes (think MVC where the genned code is your View and the code you edit should be in your Model and Controller).
Sometimes you can just expose the getComponents method from the Frame object, get all the components out by iterating through the containers and then dynamically bind them to data and code (often binding to the name property works well), I've been able to safely use form editors this way, and all the binding code tends to be very easily abstracted and reused.
If you're not talking about generated code--Well in your "God" class, does it do exactly one small job and do it well? If not, pull out a "Job", put it in it's own class, and delegate to it.
Is your GOD class fully factored? When I've seen huge classes like this, I've usually seen a lot of copy/paste/edit lines. If there is enough of a similarity to copy and past and edit some section, then there is enough to factor these lines into a single chunk of code.
If your big class is a GUI class, consider decorators--reusable and moves stuff out of your main class. A double win.
I guess the answer to your question is that in Java we just use good OO to ensure that the problem doesn't arise in the first place (or we don't--Java's certainly not immune to the problems you are talking about any more than any other language)
I am in a Introduction to Java class and I was doing a bit of research on variables. It seems that knowledgeable programers state that it is bad practice to define the variables in public visibility. I see them stating it is bad practice but I can not find a rhyme or reason to their claims. This is how I defined my variables in a application for my course.
public class DykhoffWk3Calculator
{
/*
* This class is used to define the variables in a static form so all
* classes can access them.
*/
public static double commissionRate = .03, startSalary = 45000,
accelerationFactor = 1.25;
public static double annualSales, commissionTotal, totalCompensation,
total, count, count2;
private static Object input; Object keyboard;
public static class UserInput
{ //Then continue with my other classes
I thought this was a logical method of defining them so all classes, not just main, could access them. Can someone explain to me why this is bad practice, and where variables should be defined? Any assistance would be greatly appreciated.
In short: because all of your public "surface area" for a class effectively defines its API.
If you expose things through methods, then you can change the details of how they work later. But if you expose a field, and some other class outside of your control (and quite possibly outside of your knowledge) starts referencing that field, then you're stuck with exposing that field for the rest of time. Or until you decide to break backwards-compatibility.
I thought this was a logical method of defining them so all classes, not just main, could access them.
As a general rule, you don't want "all classes" to access them. The vast majority of work with software, is spent maintaining code, not writing it for the first time. And so experienced developers realise that best practices for code, are generally the ones that make it most maintainable, not necessarily the ones that make it most convenient to write in the first place.
And if you have a variable that could be accessed from anywhere, at any time, and you want to make some tweaks to how it is modified - how can you be sure that this is safe? How long will it take you to track down all the ways that this is referenced, and determine what the effects of your change will be? (And specific to public fields, you can kiss goodbye to any sort of reusability regarding running at the same time from multiple threads, or running reentrantly.)
Broadly speaking, reducing the "surface area" of classes is a really good thing to do. Restricting the ways that other classes can interact with this one, makes it much easier to control and understand the relationships, as well as making it easier to make internal changes "invisible" to those other classes. Think about what this class does, what it will provide to other classes, as defining an interface (whether an actual interface or not). And only expose to other classes, the bare minimum that is required to fulfil those requirements.
And that never involves letting them have arbitrary access to variables.
So the general point is that you in fact DON'T want anyone to be able to access those values. Not only can I see those variables, but I can also change them to anything I like. This can lead to problems in larger, more complex programs.
Furthermore, if you wanted to later change how the class uses/stores these values, you couldn't without having to go out and change all the other classes that access those public variables directly. Instead, you should offer methods that provide just the amount of access that you want to give.
The standard analogy is that of driving a car. You know how to turn the wheel, hit the brake, etc, but not how the car actually does these things. So if the engine needed to be dramatically changed, or you got in a new car, then you'd still know how to drive. You don't need to worry about what's happening behind the scenes.
Firstly you state it wrong.
its bad to make your variable public i.e:
public String name = null; this is bad. You should always do it as
private String name = null;
To understand why, you need to dig a bit into the ideology of OOPs
OPPS ideology states that each object of your class will have 2 things:
Properties: something which we also call variables or state.
Behavior: something which we call methods or functions.
Properties identify the object over a period of time. Behaviors allow you to manage the properties of the object so that the same object over time can appear to be in different states.e.g: a Product object over a period of can be an 'Available line item' or 'Added to cart' or 'Sold' or 'Out of stock' depending on its state. Since state is critically important to the object so the object should not allow direct nonsense mutation operations on its state. Objects should keep their variables private to them and expose behaviors that the outside world can use to interact with the object and change the state based on the operation executed in the behavior. e.g: calling the 'addToCart()' behavior on the Product object that was in 'Available line item' state would probably mean: changing not just its state to 'Added to cart' but probably making other users aware that the number of this Products now available is 1 less.
So long story short: don't expose properties directly to outside work for mutation unless needed. This means dont make them public and also dont give setter methods if not needed.
By Convention Fields, methods and constructors declared public (least restrictive) within a public class are visible to any class in the Java program, whether these classes are in the same package or in another package.Which means that a change in the value of a field will definitely affect other classes accessing that field..thus breaking the whole sense of encapsulation.
Public variables in general in a class are a bad idea. Since this means other classes/programs, can modify the state of instances.
Since it is the responsibility of a class to protect its state and ensure the state is "consistent", one can enforce this by defining public setters (since this allows to run code to check/repair state).
By setting the variables public, the state is not protected. If later not all representable states are valid states, one has a problem.
Example:
Say you want to implement an ArrayList<T>, then it will look like (not fully implemented):
public class ArrayList<T> {
public int size = 0;
public Object[] data = new Object[5];
}
Now one can modify the size of the arrayList. Without adding an element. Now if you would ask the ArrayList<T> instance to remove/add/copy/...whatever, the data on which it works can be wrong.
Perhaps you can claim that a programmer is nice: he will not modify the object unless he needs to and according to the "rules". But such things eventually always go wrong, and what if you decide to modify your definition of the ArrayList (for instance using two int's for the size). In that case you would need to rewrite all code that sets such fields.
To conclude: private/protected is invented to protect a class instance from other instances that would turn the instance corrupt/invalid/inconsistent/...
I am trying to understand where good contracts end and paranoia starts.
Really, I just have no idea what good developer should care about and what shall he leave out :)
Let's say I have a class that holds value(s), like java.lang.Integer. Its instances are aggregated by other objects (MappedObjects), (one-to-many or many-to-many), and often used inside MappedObjects' methods. For performance reasons, I also track these relationships in TreeMap (guava MultiMap, doesn't matter) in addition, to be able to get fast iterations over MappedObjects bound to some range of Integer keys.
So, to keep system in consistent state, I should modify MappedObject.bind(Integer integer) method to update my Map like:
class MappedObject {
public void bind (Integer integer) {
MegaMap.getInstance().remove(fInteger, this);
fInteger = integer;
MegaMap.getInstance().add(fInteger, this);
}
...
private Integer fInteger;
}
I could just make abstract MappedObject class with this final method, forcing other to inherit from it, but it is rude. If I will define MappedObject as interface with method bind() and provide skeletal implementation -- other developer might later just forget to include it in object and implement method by himself without Map updating.
Yes, you should force people to do the right thing with your code. A great example of letting people do the wrong thing is the servlet method init( ServletConfig config ) that expected you would store the servlet config yourself but, obviously, a lot of people forgot to store the config and when running their servlets just failed to work.
When defining APIs, you should always follow the open-closed principle, your class should be open for extension and closed for modification. If your class has to work like this, you should only open extension points where they make sense, all the other functionality should not be available for modification, as it could lead to implementation issues in the future.
Try to focus on functionality first and leave all unnecessary things behind. Btw you can't prohibit reflection so don't worry too much on misuse. On the other hand your API should be clear and straightforward so users will have clear idea, what they should and what they shouldn't do with it.
I'd say your classes should be designed for as simple use as possible.
If you allow a developer to override methods you definitely should document the contract as good as possible. In that case the developer opts to override some basic functionality and thus is responsible to provide an implementation that adheres to the contract.
In cases where you don't want the developer to override parts of the functionality - for security reasons, if there is no sensible alternative etc. - just make that part final. In your case, the bind method might look like this:
class MappedObject {
public final void bind (Integer integer) {
MegaMap.getInstance().remove(fInteger);
internalBind( integer );
MegaMap.getInstance().add(fInteger);
}
protected void internalBind( Integer integer ) {
fInteger = integer;
}
...
private Integer fInteger;
}
Here you'd allow the developer to override the internalBind() method but ensure that bind() will do the mapping.
To summarize: Make using and extending classes as easy as (sensibly) possible and don't have the developer to copy lots of boiler plate code (like the map updates in your case) in case he just wants to override some basic functionality (like the actual binding).
At least you should do really everything that prevents bugs but cost no effort.
For example: use primitive types (int) instead of wrappers (Integer) if the variable is not allowed to be null.
So in your bind method. If you not have intended to bind null, then use int instead of Integer as parameter type.
If you think your API users are stupid, you should prohibit wrong usage. Otherwise you should not stand in their way to do things they need to do.
Domumentation and good naming of classes and methods should indicate how to use your API.
This question already has answers here:
Abstraction VS Information Hiding VS Encapsulation
(22 answers)
Difference between abstraction and encapsulation?
(40 answers)
Closed 2 months ago.
What exactly is the difference between encapsulation and abstraction in Java? Any brief examples would also be appreciated.
Abstraction and encapsulation are two great flavors that taste great together.
Encapsulation is minimizing what you expose to the user of your code. That "user" may be the rest of your code, or whoever uses the code you publish.
There some definite benefits to encapsulation:
The user of your code doesn't depend on parts of your program that are likely to change. When you change your program, they don't have to change their code
You are more in control of exactly how your code and state changes over the lifetime of your program. You must handle fewer scenarios, and will have fewer unexpected problems to fix
I don't know Java, but here is a small example of encapsulation in C#:
public class Giraffe
{
public Giraffe(int heightInFeet)
{
this.heightInFeet = heightInFeet;
this.numberOfSpots = heightInFeet * 72;
}
public override string ToString()
{
return "Height: " + heightInFeet + " feet"
+ " Number of Spots: " + numberOfSpots;
}
private int heightInFeet;
private int numberOfSpots;
}
Instead of exposing numberOfSpots, it is encapsulated within the class, and exposed via the ToString method.
Abstraction is using extension points to let the choice be deferred to a different part of which exact code is run. That choice could be made elsewhere in your program, in another program, or dynamically at runtime.
There are also strong benefits to abstraction:
When you change your code that implements an abstraction, the user of the abstraction doesn't have to change their code. As long as the abstraction doesn't change, the users won't have to change their code.
When you write code that uses an abstraction, you can write code once that will be reusable against any new code that implements that abstraction. You can write less code to do more.
A highly used abstraction in C# is IEnumerable. Lists, Arrays, Dictionaries, and any other type of collection class all implement IEnumerable. The foreach loop structure and the entirety of the LINQ library are based on that abstraction:
public IEnumerable<int> GetSomeCollection()
{
// This could return any type of int collection. Here it returns an array
return new int[] { 5, 12, 7, 14, 2, 3, 7, 99 };
}
IEnumerable<int> someCollectionOfInts = GetSomeCollection();
IEnumerable<string> itemsLessThanFive = from i in someCollectionOfInts
where i < 5
select i.ToString();
foreach(string item in itemsLessThanFive)
{
Console.WriteLine(item);
}
You can easily write your own abstractions, too:
public interface IAnimal
{
bool IsHealthy { get; }
void Eat(IAnimal otherAnimal);
}
public class Lion : IAnimal
{
public Lion()
{
this.isHealthy = true;
}
public bool IsHealthy
{
get { return isHealthy; }
}
void Eat(IAnimal otherAnimal)
{
if(otherAnimal.IsHealthy && !(otherAnimal is SlimeMold))
{
isHealthy = true;
}
else
{
isHealthy = false;
}
}
private bool isHealthy;
}
IAnimal someAnimal = PullAnAnimalOutOfAWoodenCrate();
Console.WriteLine("The animal is healthy?: " + someAnimal.IsHealthy);
You can use both together, as I did with IAnimal, and IsHealthy. IAnimal is an abtraction, and having only a get accessor, and no set accessor on IsHealthy is encapsulation.
These two concepts are quite different.
Abstraction is the practice of making a base class 'abstract' and then extending its functionality. An abstract class is something that doesn't exist in a concrete matter; its only purpose is to be extended. Think of if you were writing classes to represent different species. All of your different species might extend an abstract Animal class because they would all share common attributes as animals. However, you would never instantiate an Animal object, because every animal you see in the world is a squirrel, or a dog, or a fish ... or some kind of concrete implementation of that base, abstract animal class.
Encapsulation is the practice of making your class variables private, and then allowing access to them from get and set methods. The purpose of this is separate the way your data is accessed and the way it is implemented. For example, if you have some variable that has a requirement, that every time it is changed, it also increments a second variable by 1, then you would encapsulate that functionality; that way your code is more reliable because you don't have to remember to adhere that rule every time you'd access the original variable.
If you want specific code examples, I'd recommend just doing a google search, because there's a lot of examples like that available. Here's two:
http://www.tutorialspoint.com/java/java_abstraction.htm
http://www.tutorialspoint.com/java/java_encapsulation.htm
Encapsulation is to protect your member variables or methods from the outside world.
Abstraction is the way to have specific implementation. that is which implementation to use is unknown to the user.
Encapsulation is part of abstraction. The notion of abstraction is one of creating an object to represent another object. Typically, the original object is more complex than the abstraction. An abstraction is thus a representation, usually as an aid to memory, for terminology/communication etc. Think of it like this: abstract art is a representation of something else. A steering wheel, gearshift and 2/3 pedals is an abstraction of how a car works.
Basically, the abstraction allows you to represent something complex, with a lot of details, as something a lot simpler. In my opinion, this is related to 'chunking' in cognitive science. We're not able to keep complex things in our head, so we simplify by abstracting, then using the abstraction. Design Patterns are another great example. Instead of talking about details, we can talk about Command, State or Strategy pattern etc.
Encapsulation is part of forming/creating an abstraction. The smaller an object's interface, the easier it is to abstract. You don't need to know how an engine and gearbox work to drive a car, you just need to understand their abstractions (gear shift and accelerator). The details of the engine and gearbox are encapsulated (into the interface) in order to create the abstraction.
Encapsulation is needed for abstraction because an abstaction can't deal with all the real details and complexity (otherwise its not an abstraction). So the gearshift is an incomplete representation (or model) of a gearbox, but its complete enough for everyday use. Encapsulation can be thought of as 'hiding details', which is necessary for creating a simpler representation.
Its also important to discuss the concept of an 'interface'. For the most part, the terms 'interface' and 'abstraction' are more less interchangeable in this instance. An interface is the part of a system with which the user deals or interacts. The interface to a car is the steering wheel, gear shift and pedals etc. The abstraction produces an interface. You don't deal with the engine/gearbox directly, you deal with their respective interfaces.
Another reason for encapsulation is because we're dealing with an incomplete model/abstraction, we don't understand the full complexity of the original, and can't be trusted to deal with all the variables (because we don't understand the full model). This is important for decoupling, because without abstraction, interacting components would know too much about each other. Think about it, because every car has a steering wheel, pedals and gearshift, you can drive any car, regardless of engine type etc. Also, the gearbox is abstracted from the engine. Otherwise each custom engine would need a custom gearbox.
Similarly, a Class is an abstraction. The class represents some complex model, through its interface - the public members of the class. This interface is created through encapsulation. The class presents a simplified interface of its more complex implementation to its collaborators. You can also think of it as a 'need to know' situation. The collaborators of the class don't need to know exactly how it works. Just as you don't need to know how an engine works to drive a car.
Encapsulation, interfaces and abstraction play a critical role in cohesion and coupling, and therefore maintenance of your code. If you don't create good abstractions, and violate the 'need to know' principle, then your code becomes entangled, fragile and a nightmare to change, because there is no 'buffering'. The OO concept of 'tell don't ask' is also related to this.
My colleagues and I were having a discussion regarding logic in enums. My personal preference is to not have any sort of logic in Java enums (although Java provides the ability to do that). The discussion in this cased centered around having a convenience method inside the enum that returned a map:
public enum PackageType {
Letter("01", "Letter"),
..
..
Tube("02", "Packaging Tube");
private String packageCode;
private String packageDescription;
..
..
public static Map<String, String> toMap() {
Map<String, String> map = new LinkedHashMap<String, String>();
for(PackageType packageType : PackageType.values()) {
map.put(packageType.getPackageCode(), packageType.getPackageDescription());
}
return map;
}
}
My personal preference is to pull this out into a service. The argument for having the method inside the enum centered around convenience. The idea was that you don't have to go to a service to get it, but can query the enum directly.
My argument centered around separation of concern and abstracting any kind of logic out to a service. I didn't think "convenience" was a strong argument to put this method inside an enum.
From a best-practices perspective, which one is better? Or does it simply come down to a matter of personal preference and code style?
Well, I've done this before but that certainly doesn't mean it's the 'best' thing to do.
From my perspective, though, I would prefer to have that logic on the enum, for the same reason you wouldn't move a 'toString' method out to a service. The logic only concerns the enum itself, and its own representation.
I think it would be misleading to move such a method out to a service - by placing it on the enum you are being up front about the fact that the enum has a 'toMap' method. Someone who didn't know about the service and was just looking at the enum may not know that.
It also helps with auto completion in IDE's - I can hit the '.' key and instantly see methods provided by the object.
I think it probably comes down to personal preference and whether or not you think the logic might change in the future.
The best use case for enum logic (since it's pretty static) is for things that aren't going to change. The logic in java.util.concurrent.TimeUnit is a pretty good example of this: the conversion factors between time units are well-defined and won't ever change, so it's a good candidate for static logic to embedded within the enum.
I cannot see any persuasive reason why it is "good practice" ... or "bad practice" ... to do what you are suggesting.
I'm inclined to go for the convenience argument. But frankly, this is not the kind of thing that it is productive to spend man-days debating ... IMO.
I have tried logic in enums a few times, but the only thing I am ever really happy about is something like:
// not compiled, so might have errors...
public enum Foo
{
A,
B;
// not complete, doesn't properly handle invalid cases...
public static Foo fromString(final String str)
{
final String strLower;
final Foo val;
strLower = str.toLowerCase();
if(strLower.equals("a")
{
val = A;
}
else if(strLower.equals("b")
{
val = B;
}
else
{
throw new IllegalArgumentException(/*...*/);
}
return (val);
}
}
Generally once you start adding instance variables/methods you should probably be doing something with a proper class.
I'd start with putting it in the enum. If there will be only one toMap() method in the system, having an extra class is surely unnecessary and will be annoying.
If I had bunch of enums from which I want to create such map, or maybe anticipate such situation, THEN I'll create a static utility class, and a generified utility method to do that.
My personal opinion is, practicality tramps theory.
EDIT: Oh wait, this would be difficult to provide a generic utility method for.. In that case, if the method is going to be that enum specific, I'd definitely go with putting it in the enum. If I were the maintenance programmer, I'd be very dissatisfied if you would have an extra class that I have to look for.
Like anything it would depend on the usage, there are general rules but practicality should always win the argument. What is the map used for? Would you ever need to restrict the contents of the map, e.g. if the map is used to populate a combo box, is there ever the need to remove some choices, say if some carriers only handled certain package types a strategy could be used to populate a map, that would be best done outside of the enum.
Despite that, my preference would be to have a create the map elsewhere, that extra level of indirection is never a hindrance to flexibility and could save a lot of grief and adds little overhead now. And you can also code it so you can get similar functionality with other enums.