Why should I use get and set for my class methods?

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Why should I use get and set for my class methods?

Postby BotoBoto » Sat Dec 17, 2011 10:23 am UTC

I'm making a class in PHP which will handle image/video uploading/editing/administration.

But I'm having trouble seeing why I should use get_videowidth while i can also use $media->width?
User avatar
BotoBoto
 
Posts: 194
Joined: Mon Mar 09, 2009 9:31 pm UTC

Re: Why should I use get and set for my class methods?

Postby Sc4Freak » Sat Dec 17, 2011 10:50 am UTC

The reason for using getters and setters is encapsulation. They protect clients of the class from changes in the internal implementation. You might want to add some debug checking whenever someone gets the width of a video, for example. Or you might want to enforce an invariant that width == height in the setter. Or whatever.

Using getters and setters makes this easy. But if everyone has direct access to fields in a class, then it becomes much harder - you have to find every location in your code that uses the field you want to change and fix it.
User avatar
Sc4Freak
 
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Why should I use get and set for my class methods?

Postby Ubik » Sat Dec 17, 2011 11:08 am UTC

In PHP you can use the __get and __set magic methods to have greater control on the usage of public properties. When you access a property that doesn't exist as public property already, __get is called with the property name as parameter ($obj->property is the same as $obj->__get("property") if property isn't public). When setting a property value, __set is called with the name and value ($obj->__set("property", $somevalue)). You can do the checking and enforcing in there if you need to.

The annoying thing with those magic methods is that access to all properties is done via them, so you need to resort to a switch/if-elseif-construct or some dynamic method calling cleverness to delegate the handling to an hidden getter/setter method. And at that point the use of the methods is mostly adding to the convenience of the user (by few written characters).

Edit: Links to relevant PHP documentation pages: magic methods, overloading
User avatar
Ubik
 
Posts: 807
Joined: Thu Oct 18, 2007 3:43 pm UTC

Re: Why should I use get and set for my class methods?

Postby Steax » Sat Dec 17, 2011 12:10 pm UTC

For context, Ubik is talking about magic get and set, which means you can set and call arbitrary variables (i.e. $foo->something = "baz") and have functions to manage that process. This lets you conveniently access things through that syntax, instead of some awkward $foo->setBar("something", "baz") syntax. There's also the __call magic function, which acts similarly, but for functions.

I assume Botoboto is talking about get/set methods used as a replacement for simply setting variables.

Indeed, the main reason is encapsulation. Sometimes there are additional things you need to do when you set a variable, for instance. Consider it a 'hook' for more functionality.

By the way, if you're trying to make a simple library for handling your media, consider flourish. It's a pretty bare-bones library, but it gets the basic things you want done. It'll handle uploads, validate MIME types, move files around and rename them uniquely, resize, crop, and flip images, etc. Even if you don't want to use it, you can always browse their source for ideas on how to implement your code.
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 2772
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Why should I use get and set for my class methods?

Postby Carnildo » Sat Dec 17, 2011 10:43 pm UTC

Sc4Freak wrote:The reason for using getters and setters is encapsulation. They protect clients of the class from changes in the internal implementation. You might want to add some debug checking whenever someone gets the width of a video, for example. Or you might want to enforce an invariant that width == height in the setter. Or whatever.

They also let you get and set values that don't actually exist. For example, you might have an $image->get_area() that returns $image->width * $image->height, or an $image->set_area() that adjusts $image->width and $image->height to give an image with the specified pixel count while preserving aspect ratio.
Carnildo
 
Posts: 1961
Joined: Fri Jul 18, 2008 8:43 am UTC

Re: Why should I use get and set for my class methods?

Postby Thesh » Sat Dec 17, 2011 11:02 pm UTC

It's generally accepted that getters and setters should be used even if a variable will be suitable. The general idea being that changing a public variable to a getter/setter method in the future is very difficult in many cases. In PHP it might not matter, but if you distribute a C++ library, then every single program that uses it will have to be altered for your change. It's just good practice to never expose the internals of your class in OOP.
Eppur si mouve.
User avatar
Thesh
Has the Brain Worms, In Case You Forgot.
 
Posts: 2573
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Southern California, USA

Re: Why should I use get and set for my class methods?

Postby BotoBoto » Mon Dec 19, 2011 6:37 am UTC

Thanks guys, I think I understand it. The class should be more closed off and simple things such as get_area() or $user->get_profile() or something should be done via the class itself, not outside of the class which defeats the purpose of having a class.

Or am I misreading things here?

BTW speaking of classes to manipulate media, ffmpeg is a bitch to install on my ubuntu, let alone my windows.
User avatar
BotoBoto
 
Posts: 194
Joined: Mon Mar 09, 2009 9:31 pm UTC

Re: Why should I use get and set for my class methods?

Postby Steax » Mon Dec 19, 2011 8:45 am UTC

Say I have a File object. Now, I could lay it out like this...

Code: Select all

$size 
= $file->size;
$oldcontents = $file->contents;
// add new contents
$file->contents = "foo";
$file->save();
 


But that has a heavy mixup of variables and functions. Functions should be used where you're actually doing something, even if you don't actually need to run a full function for it.

This might be more appropriate:

Code: Select all

$size 
= $file->getSize();
$oldcontents = $file->getContents();
$file->setContents("foo");
$file->save();
 


You can see that you now have hooks for future functionality, and you can clearly see when an operation is being done. In my first implementation, I could have simply stored the file contents in a variable, and later write it to the file when I execute the save() method. But by using functions instead, I can now do actions whenever I get or set contents; for example, I could have the object store the timestamp of my last edit when I did my setContents() call. I could have it record how many edits I did. I could have it do a diff on the previous contents, and just store the diffs instead of the full data, which may allow for smaller files or specialized files or whatnot. And I could do that without having to touch a single setContents() line.

It's also less error-prone; I've seen bugs like this:

Code: Select all
// ...
if($file->contents "foo"){
   
// ...
}
// ...
 


This can be a bit tricky to debug since it'll always be true, and your eyes are trained to skip over that if clause because it's so short and you've seen the if(a==b) line a million times. Trying to set a function will cause PHP to explode.
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 2772
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Why should I use get and set for my class methods?

Postby RoadieRich » Mon Dec 19, 2011 2:49 pm UTC

The other solution there is always to write your comparrisons with a literal the other way round;

if ("foo" == $file->contents)

That way, it's again an error if you omit an equals sign. Or it should be, in most sensible languages - but then it is php we're talking about.
roband wrote:Mav is a cow.

UniJam 2012: Inter-university Games Jam hosted by Nottingham Trent University DevSoc.
nlug: Nottingham Linux User Group
DevSoc: The Nottingham Trent University Software Development Society
User avatar
RoadieRich
The Black Hand
 
Posts: 1030
Joined: Tue Feb 12, 2008 11:40 am UTC
Location: Somewhere only we know

Re: Why should I use get and set for my class methods?

Postby BotoBoto » Mon Dec 19, 2011 5:09 pm UTC

Now
RoadieRich wrote:The other solution there is always to write your comparrisons with a literal the other way round;

if ("foo" == $file->contents)

That way, it's again an error if you omit an equals sign. Or it should be, in most sensible languages - but then it is php we're talking about.


True, true.

My biggest problem with all of this, is how to structure it? I've looked at symphony for creating structure in my code, because I don't know what's useful. I mean I want it to flow properly, be modular, and not hard to maintain. But I HATE examples which use bikes. I was thinking of somethingl ike this

database class
(optional) Mysql class
(optional) any other database type
session class
user class
permissions (auth) class
template class (smarty)

module class for pages that use a lot of modules/have a lot of pages like a preferences page

But this will all be used within a spaghetti code environment. I can't seem to get a good maintainable grip on the structure of my code.

Any words of advise?
User avatar
BotoBoto
 
Posts: 194
Joined: Mon Mar 09, 2009 9:31 pm UTC

Re: Why should I use get and set for my class methods?

Postby Steax » Mon Dec 19, 2011 11:03 pm UTC

I mentioned them earlier, but take a look at the docs for Flourish. They use singletons, which may not be optimal, but it's an interesting look at how you can lay out your code. They have online API and source code documentation.
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 2772
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Why should I use get and set for my class methods?

Postby OmenPigeon » Tue Dec 20, 2011 4:02 am UTC

BotoBoto wrote:I don't know what's useful. I mean I want it to flow properly, be modular, and not hard to maintain. But I HATE examples which use bike

There's a good heuristic that you should refactor code so it's shared once you've written the same code three times.1 There's a really strong temptation to start refactoring for ULTIMATE MODULARITY as soon as you (or I, certainly) start writing anything that seems like it might have generic utility. Resist that. The problem is that if you're only going to use a piece of code once, there's no point in refactoring it. Any modularity you add is wasted effort: it's often harder to maintain a database wrapper that's spread across five different layers of code than it is to maintain something in one class. If you notice that you've written basically the same code in two places then we're getting somewhere. Continue to resist the urge to refactor though. It's really easy to write two pieces of code that seem the same, but are actually very different, or are going to become very different. If you prematurely refactor those into a single function or class, you'll more than likely end up with something that tries to be two subtly different abstractions at once. This leads to some really quite painful bugs and suffering. Once you've written code three times, then you tend to see what the actual patterns are, and what the incidental parts are.

This is, of course, just a heuristic. It's not like seeing the same code written three times grants some sort of enlightenment, while seeing it twice doesn't. And it's perfectly fine to do whatever you feel like as long as you know what you're doing. Just this afternoon, for example, I refactored some code that had only been written (*gasp*) twice. I happen to know that I'm going to need to reuse that code three or four times more in the next week or so, so I went for it. On the other hand, I didn't push the refactor as far as I could have. There's still about five lines of duplicated code in this pair of methods. But getting rid of that is going to be substantially harder (at least, it is in Java), so I'm putting that work off until I have more instances of the problem to work on.

Coming back to your original problem: if you don't know what's useful, just do whatever. It's almost impossible to predict what's going to be hard to maintain until you run into a maintenance problem. If you want to get your code to an easily maintainable state as fast as possible, the best thing to do is probably to get it to a horribly broken and unmaintainable state as fast as possible, then work from there. Until you've got pain, you won't know where to apply the painkillers.2 The other option, endlessly refactoring, leads most often to no code at all. At least in my experience. Crappy spaghetti code that works and does something useful is far superior to beautiful code that doesn't actually solve the problem at hand.

1: I don't remember where it comes from. I think I've heard it attributed to everyone from Knuth to Norvig.
2: These are topical painkillers, okay? In this metaphor we haven't invented tablet painkillers yet.
As long as I am alive and well I will continue to feel strongly about prose style, to love the surface of the earth, and to take pleasure in scraps of useless information.
~ George Orwell
User avatar
OmenPigeon
Peddler of Gossamer Lies
 
Posts: 671
Joined: Mon Sep 25, 2006 6:08 am UTC

Re: Why should I use get and set for my class methods?

Postby Steax » Tue Dec 20, 2011 4:51 am UTC

The best rule of thumb is that whatever you're making, someone's already had to do it before. I abuse (modular) libraries to their limits. Go browse round them, take libraries you like, throw them somewhere in your server, and include them on-demand. Don't copy bits and pieces for each project. Just grab one and go.

For added obvious pointers, Flourish has a (cross-database) Database object, a session object, a permissions object, a rudimentary templating object (though you can just toss your own in, too), and you can use standard ORM for that user class.

There's also Moor that handles the Controllers part of MVC, so no more messing around with URL regexes in .htaccess files. There are many libraries that play friendly with others and are completely plug-and-play, so try them out.
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 2772
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Why should I use get and set for my class methods?

Postby BotoBoto » Tue Dec 20, 2011 7:45 am UTC

Steax wrote:The best rule of thumb is that whatever you're making, someone's already had to do it before. I abuse (modular) libraries to their limits. Go browse round them, take libraries you like, throw them somewhere in your server, and include them on-demand. Don't copy bits and pieces for each project. Just grab one and go.

For added obvious pointers, Flourish has a (cross-database) Database object, a session object, a permissions object, a rudimentary templating object (though you can just toss your own in, too), and you can use standard ORM for that user class.

There's also Moor that handles the Controllers part of MVC, so no more messing around with URL regexes in .htaccess files. There are many libraries that play friendly with others and are completely plug-and-play, so try them out.


I am able to make basic classes and their uses, but my biggest concern is the way I code. Will flourish/moor help me clean up how I code things? As in when and how I call classes/when to use functions? Ill certainly take a look.
User avatar
BotoBoto
 
Posts: 194
Joined: Mon Mar 09, 2009 9:31 pm UTC

Re: Why should I use get and set for my class methods?

Postby Steax » Tue Dec 20, 2011 10:13 am UTC

I like Flourish's code because:
- it's built with security in mind, so you can learn a lot from the code there
- it tries to implement the basic code you use over and over, so you can see their way of doing things (i.e. take it look how it identifies MIME types)
- has many interesting approaches to common problems in the web, and may well inspire you to create some things in their model (i.e. their authentication system)
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 2772
Joined: Sat Jan 12, 2008 12:18 pm UTC


Return to Coding

Who is online

Users browsing this forum: No registered users and 6 guests