Java on Android

Started by Ryan Timothy B, Thu 19/04/2012 04:48:55

Previous topic - Next topic

Ryan Timothy B

So I'm currently learning programming for the AndroidOS when I ran into some contradictions between the author of the book I'm reading, what he says and then does in his own code.

He says in a quick best practices summary at the end of the chapter:
QuoteBest Practices
[..]  You should maybe avoid getters and setters as well.


I did a little research and found this on the Android Developer website on getters and setters:

QuoteAvoid Internal Getters/Setters

In native languages like C++ it's common practice to use getters (e.g. i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.

On Android, this is a bad idea. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter. This is true in Froyo, but will improve in the future when the JIT inlines getter methods.



Then a lot of his code in the book uses getters and setters for no apparent reason (I'm not done the book yet - so perhaps he adds more to these getters and setters throughout but I doubt it)?

Here's an example:

Code: ags
public class AccelerometerHandler implements SensorEventListener {
	float accelX;
	float accelY;
	float accelZ;
	
        // [.. removed nonessential code that took the accelerometer changes and values and set them to the accelXYZ variables ..]
	
	public float getAccelX()
	{
		return accelX;
	}
	
	public float getAccelY()
	{
		return accelY;
	}
	
	public float getAccelZ()
	{
		return accelZ;
	}
}


I don't want to learn bad habits from someone who is supposed to be teaching me not to do something a certain way and then does it himself.

So why is it he suggests not to use getters and setters then he uses them all over his code? Just to encapsulate his code? To keep things looking neat for those learning from him? Should I change these to public variables and ditch the getters and setters he has in all his code examples?

Edit: Or does internal mean from within the class? Does it still apply in this instance?

Snarky

Yes, internal means within the class.

QuoteIt's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

That's what he's doing.

Ryan Timothy B

Alright, that's mainly what I figured but I kept wondering what's the difference? Using a getter/setter within the class or as the public interface, you'd think both would be just as slow and calling the variable itself would be faster.
Ie: AccelerometerHandler.accelX vs AccelerometerHandler.getExcelX()

But I have no idea what the eclipse compiler does. As far as I know it removes the use of the public getter/setter function and makes it direct upon compile. I doubt it.

To me it just looks like bad practice, but I've never taken any programming classes since high school and I was never taught proper coding methods. On a mobile device I can't afford to hog the CPU.

Snarky

There are good reasons for using getter and setter methods. The idea is that outside parts of the code shouldn't get to mess around with the data inside your object willy-nilly, but always have to use its defined API. Getter and setter methods provide that API, and can do things like validating the input, making sure it doesn't get changed while you're in the middle of using it, or convert from one representation to another. That makes the program more secure and can help avoid bugs. In this case, it looks like the programmer is ONLY providing the getter methods, so that the values are read-only from outside the class. That's a very good reason to use the getter/setter pattern.

And at the same time, outside code shouldn't have to care about the data inside your object; you should hide as much as possible, including how things are stored internally. That keeps things simple, and means that you can change it later without having to update all the code that refers to it (e.g. instead of having a float field for each property, you could define a new data type that stored them all together and store it inside on of them, and you could keep the same getter methods, just change how they're implemented).

That's a quick explanation of why getter and setter methods are considered good programming practice. So programmers got in the habit of always making all fields private or protected, and only providing public access to them by getter/setter methods. That leads to a lot of getter and setter methods that do absolutely nothing apart from reading from and writing to the underlying field, which is almost certainly never going to change, and is only ever used within this particular program. And yes, that's kind of pointless, but modern editors let you auto-generate those methods, and many compilers can often eliminate them automatically, so it doesn't matter much. (Also, Java is probably more hard-core on this concept than many other object-oriented languages, tending to use methods for everything.)

I think the advice is a bit strange, since he still recommends keeping them for the public interface, while from inside the class itself you don't really ever need to use them in any case (unless they do something like validation or data conversion). At least I rarely call my getters and setters from inside the class code.

The performance hit on Android probably sounds more serious than it is. A few extra virtual method calls aren't going to matter much compared to keeping the logic of your program clear and streamlined, and avoiding unnecessary processing (e.g. only updating the screen when it actually changes, and only the parts of the screen that has changed, instead of every loop regardless... things like that), which is easier when you follow best practices. I think you should use getter/setter methods until you've internalized them; once you have a good feel for the benefits, you might consider not bothering with them for some trivial cases. Just be prepared that a lot of people are going to consider it bad code if you do so.

Monsieur OUXX

For short: using internal getters and setters is a good pratcice if you're a big company that intends to have perfect source code, meant to be maintained --and upgraded-- for the next 2 billion years.
Otherwise, if you're a "normal" guy who wants to keep his sources readable and slightly faster, then just don't use then.

Both are good practice depending on what you're trying to achieve: It's readability versus error-safe.
 

Snarky

... and getters and setters for external access is always good practice.

Ryan Timothy B

Good points. I'm not sure which route I'm willing to take, perhaps I'll keep the external ones for the "good practice" reasons.

Paper Carnival

It boils down to this: Prevent the users of your classes from making mistakes. Even if the user is just yourself. Always assume that he is a horrible human being who never reads the manual.

Now, you might be absolutely certain that a special attribute is safe without the need of a getter/setter, especially when it's a primitive type (e.g. an integer that holds the age of a person). Even so, using getters/setters is a good idea because not only does the code look more uniform, but you might need that functionality later. If you are using the member "age", but finally decide that you need accessors for safer access, you will have to change that everywhere you reference that. True story, it has happened, and it will also happen to you eventually.

Other languages like C# or Ceylon offer the ability to use Properties, which act like getters and setters except they are used like normal members. However, since the creators of Java assume that most Java developers are horrible human beings who hate the users of their classes, it doesn't support that feature so that it can't be abused.

SMF spam blocked by CleanTalk