oop question

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: oop question

Post by alex.barylski »

My accessors/mutators are generally just that, solely keeping implementation data away from public access. It's allowed me to change conventions from the C++ prefix underscore for private data to none-underscore which lets me use more descriptive variables, whereas the prefixed underscore always influences me to use brief names, as I found they looked nasty when something like this:

Code: Select all

private $_first_name
Without the prefix '_' it doesn't anywhere near as bad.

Anyways, an example of mutator/accessor:

Code: Select all

class Front{
  private $registry = null;
 
  public function setRegistryObject($registry)
  {
    $this->registry = $registry;
  }
  public function getRegistryObject()
  {
    return $this->registry;
  }
 
}
I guess what confuses me, is what difference does it make to the SUT whether you inject a mock registry or the real thing, so long as the API is what is expected everything should continue as expected? I wuld like to see an example of when you experience problems with acccessors/mutators over direct access. Essentially mutators/accessors do give you direct access, only through a method interface, as opposed to data -- coming from a C++ background this has always been a no-no -- although many practices from C++ do not persist in PHP so I'm open to new ideas... :)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: oop question

Post by Jenk »

A Unit Test is not a Unit Test if there are dependencies. :)
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: oop question

Post by alex.barylski »

A Unit Test is not a Unit Test if there are dependencies.
Ok...that being said...my method of accessor/mutator would not pose any problems while testing with mocks or otherwise, would it? I guess why I am confused about your incessant dislike/hatred for privates is that I have never experienced a problem with them in any of my tests (good chance I'm doing something wrong I suppose).

The only issues I had were right at the start, with having to mock/stub concrete dependencies, like calling on a static model inside a controller:action method, to which you answered, use a service locator -- which worked wonderfully. :D

Other than that one experience I have never had actual problems with testing, short of general theory/best practice/etc.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: oop question

Post by Jenk »

I've only ever encountered problems with private members, no positives, ever.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: oop question

Post by kaisellgren »

Just popped in my mind - I think it was one of the PHP developers at Zend who once said "better be proactive than retroactive". Personally I am trying to be just that - I don't change my code when I encounter a problem, I try to "predict" potential problems, although sometimes I fail to do so.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: oop question

Post by alex.barylski »

I've only ever encountered problems with private members, no positives, ever.
Can you give an example of a situation in PHP where you encountered these problems?
I don't change my code when I encounter a problem, I try to "predict" potential problems, although sometimes I fail to do so.
Thats how the NASA team do it :D
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: oop question

Post by Jenk »

Testing that a dice roll is between 1 and (number of sides)

the only fool proof way to assert that test is to set what ever value for "current side" is outside of those boundaries, then roll.

Code: Select all

class Dice {
  public $currentSide;
  public $numberOfSides;
 
  public function __construct ($sides = 6) {
    $this->numberOfSides = $sides;
  }
 
  public function setSide($side) {
    if ($side < 0 && $side > $this->numberOfSides) {
      throw new ArgumentException("Side must be between 1 and {$this->numberOfSides}");
    }
    $this->currentSide = $side;
  }
 
  public function roll() {
    $this->currentSide = rand(0, $this->numberOfSides);
  }
}

Code: Select all

public function testDiceRoll() {
  $dice = new Dice(6);
  $dice->currentSide = 10;
  $dice->roll();
  $this->assertTrue($dice->currentSide > 0 && $dice->currentSide <= 6);
}
As for "predictions" well, you've already said you sometimes fail to do so.. so why bother in the first place? There is a balance to maintain, I'll happily agree that some due diligence is necessary, but on the whole you should only be positively testing. Negative testing is impossible to complete as there are endless use-cases and edge-cases that can be cooked up. We've had this issue before, our MD (Managing Director) used to be adamant that we test our software to the nth degree before release.. until he finally realised how much of a delay this was costing both us and the clients (who didn't get their software until much later because of this exhaustive testing!).

If it does the job you want, it's done. I think it was Ward Cunningham or Kent Beck who said "Only do what is the absolute minimal required to complete the task, and nothing more." Which simply translates to "Does it do what was asked?" and not "Does it do what was asked, and does it not do everything else?"
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: oop question

Post by kaisellgren »

Jenk wrote:As for "predictions" well, you've already said you sometimes fail to do so.. so why bother in the first place?
Well, I think it is just the way I am used to work. Most of my time I deal with security issues. Lately one of my friends wrote an application where he directly outputted data from the database. He said that there are no security problems, because the database input was coming solely from the site owner. If I understood you correctly, this would be exactly what you would also do? There is no point in handling the output data, because it comes from the trusted person? Personally, I always take care of potential issues. I want to have solid, secure and bug free code. In this case, someone might be able to hijack into administrator's session and inject malicious XSS, or perhaps the behavior of the site changes in the future? You just can't know what is going to happen, but you can predict that and possibly stop it. Even if I can proactively stop only 10% of the bugs in my applications, I am happy to do so. If I was the one who where coding the application, I would encode/escape the output even though it comes from the administrator.

There's a saying "look before you leap". Whether a programmer follows it or not, that's his decision.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: oop question

Post by Jenk »

No, I wouldn't allow unescaped data to enter the DB.. but then I would be using a DataLayer that would take care of that for me, and so it would make no difference to my effectiveness and efficiency in delivering what the customer wants. :)
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: oop question

Post by alex.barylski »

Kent Beck who said "Only do what is the absolute minimal required to complete the task, and nothing more." Which simply translates to "Does it do what was asked?" and not "Does it do what was asked, and does it not do everything else?"
Kent Beck - XP Explained...I read that book too. :P I'm pretty sure that is where I heard that statement anyways.

I haven't really looked at your example as Im work so I can't say I understand, agree or disagree, but I appreciate the reply and will read it more thouroughly later on.

Cheers,
Alex
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: oop question

Post by Weirdan »

Jenk wrote:No, I wouldn't allow unescaped data to enter the DB..
Does that mean you would be storing data encoded for injecting into the html in the database?
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: oop question

Post by Jenk »

Depends on requirements. If it's a CMS with an editor like TinyMCE, yes, definitely ;)

If the client does not want to allow html, then it would be encoded/stripped as per requirement.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: oop question

Post by kaisellgren »

That's called Input Encoding. You could also ask it with simpler terms "do you encode input?". It's a more efficient way to handle encoding, but less secure than its counterpart Output Encoding.
Jenk wrote:If it's a CMS with an editor like TinyMCE, yes, definitely ;)
If the client does not want to allow html, then it would be encoded/stripped as per requirement.
So, you use input encoding for WYSIWYG's? I'm not sure why do you see it as a better choice for WYSIWYG's. I mostly encode the output while the data itself is non-encoded in the database. If you are allowing arbitrary users to enter HTML on your site, then I think the reason for choosing input encoding is performance? You don't want to encode the same data every page load? That's usually why people use input encoding - for performance. Sometimes when I do it (I want maximal performance) and I still want to have a high secure application, I take a fingerprint of the data and I check if it matches. It increases your security in a way of keeping database crackers away from doing XSS attacks and the approach is part of the "minimize attack surface area" -principle. It's a good way to build secure applications. If someone ever cracks into my server's database, he will have damn hard time finding out how to gain any use of that (other than altering/removing data, which is backuped or exist on another slave server anyway). This, however, requires good database credential handling and lots of other minor aspects to be done.

Fingerprinting - just something you might be interested in when you play with your input encoding. Note: almost no one uses fingerprints, so, I think it's pretty much useless to try to google for it. :P I actually think no one ever does this, because it's a sort of deeper level security measure which not being implemented does not make your application inherently crackable.

Anyway, sorry for the off-topic.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: oop question

Post by Christopher »

kaisellgren wrote:That's called Input Encoding. You could also ask it with simpler terms "do you encode input?". It's a more efficient way to handle encoding, but less secure than its counterpart Output Encoding.
Actually neither is more or less secure and both should be used. Input should be filtered via a white list. No good security option uses black listing. And the output should be escaped and special chars encoded.
(#10850)
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: oop question

Post by kaisellgren »

arborint wrote:the output should be escaped and special chars encoded.
What kind of situation are you talking about here? In general, encoding/escaping is accepted to be the "same" term. Usually encoding is used when the output goes to a user, and escaping is used for outputting data into somewhere else (LDAP, FTP, Shell, databases, ...), but they both have the very same goal: to make sure that the meaning of the data is understood correctly in the certain context - "text" in HTML, "data" in a database and so forth. Encoding is more of a modifying the actual data while Escaping is just making sure it is understood correctly on the context, but these two words are often used together and often referred to the same situations like if you read OWASP, they sometimes refer to encoding or escaping of HTML meta characters.
arborint wrote:Actually neither is more or less secure and both should be used.
Really depends on the situation. Consider:

Code: Select all

$encodedHTML = fetchDataFromSQL();
echo $encodedHTML;
is this as secure as:

Code: Select all

$encodedHTML = encodeForOutput(fetchDataFromSQL());
echo $encodedHTML;
?

Nope, even if the data is handled by a trusted source, the code leads to a security mistake from the coder's part when someone has cracked into your database.

Consider this:

Code: Select all

$newEmployees = fetchFromExternalServer();
echo "New employee list: $newEmployees.";
The above code might rely on Input Encoding (which is done on the remote server). The data is encoded on the remote server, but if the server fails (or anything in between) - so does this code.

Code: Select all

$newEmployees = encodeForOutput(fetchFromExternalServer());
echo "New employee list: $newEmployees.";
This, on the other hand, would corrupt the data, because there are now two levels of encoding: Input and Output applied at the same time. Probably the easiest way to code this securely would be to only use Output Encoding (and revert the Input Encoding applied by the remote server if it is needed). Depends really on the overall implementation of the application and the relationship between the servers.

Sometimes if you keep a database separate from the server and you forget to use SSL - a MITM attack could at least in theory completely bypass Input Encoding attempts. I tried this on my EEE and primary PC, setuped a separate DB server and modified the data on fly, but is nearly impractical to do in real life situations, though. To sum up, in certain situations, Output Encoding is more secure than Input Encoding, because you can't always ensure the data integrity - unless, of course, you use some sort of fingerprints as I noted. So, it's if, if and if. Depending on the situation, Output Encoding can certainly be more secure than Input Encoding when comparing the two alone. The same thing does not really apply to Escaping as you can't distinct between Output and Input Escaping... that's one thing that separates the two words and as you said Escaping should be applied. Actually, Escaping must be applied imo even if you are doing something like passing a casted integer to an integer column.
Post Reply