PHP OOP

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
[)roi(];18161375 said:
Let me stir the pot; the only programmers still doing exclusively OOP are probably too dense to grasp FP concepts :whistling:

Well I am assuming that being a flippant comment. If not, I can say that functional programmers didn't cut it as OOP programmers. :whistling:...

Quite honestly, the links you have is the opinion of a person that probably did not get it. That is obviously not representative. Not saying OOP is for everyone and every task. It's just that in my day to day programming I get the advertised benefits. To me, code reuse is very important not only from a turn-around time point of view but also quality.

In my ERP my domain layer follows functional programming style whereas some other components follow OOP. Use the correct tool.

Like a friend once said: "He adjusts his architectural design to his skill set."
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
PHP is like the R5 hooker on the corner of the street. Sure you can do anything and as much as you'd like and it's cheap and quick... but STD-prone if not used right
Really? :wtf:, so what language (according to you) isn't "STD-prone"?
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Well I am assuming that being a flippant comment. If not, I can say that functional programmers didn't cut it as OOP programmers. :whistling:...

Quite honestly, the links you have is the opinion of a person that probably did not get it. That is obviously not representative. Not saying OOP is for everyone and every task. It's just that in my day to day programming I get the advertised benefits. To me, code reuse is very important not only from a turn-around time point of view but also quality.

In my ERP my domain layer follows functional programming style whereas some other components follow OOP. Use the correct tool.

Like a friend once said: "He adjusts his architectural design to his skill set."
Sorry that's BS; the reality is just the reverse. At one point I was a OOP programmer, before that strictly imperative, and after all of that FP is a god send.

I still use OOP, but in a very limited capacity, typically only for events handling e.g. UI. The majority of the codebase, including data structures are modelled with protocol(interfaces) tied in immutable structs (similar to final / sealed classes). As example I recently was contracted to convert a few in-house legacy Objective-C and Objective-C++ codebases (> 50,000 LOC) to Swift; using an extensively an FP style, the new apps ended up with just over 14,000 LOC. My takeaway from this -- many OOP programmer's are just to adept at recreated spaghetti code with object hierarchies; when it was never justified.

PS... FP (as you should know ;)) is all about code reuse, far more so than OOP, for example: every FP function has to have all it's inputs defined as parameters i.e. hidden state, hidden input and global variables are specifically avoided... OOP is just the opposite; so code reuse is far more complicated with OOP.
 
Last edited:

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
[)roi(];18161665 said:
Sorry that's BS;
Your opinion dude

[)roi(];18161665 said:
I still use OOP, but in a very limited capacity, typically only for events handling e.g. UI. The majority of the codebase, including data structures are modelled with protocol(interfaces) tied in immutable structs (similar to final / sealed classes). As example I recently was contracted to convert a few in-house legacy Objective-C and Objective-C++ codebases (> 50,000 LOC) to Swift; using an extensively an FP style, the new apps ended up with just over 14,000 LOC. My takeaway from this -- many OOP programmer's are just to adept at recreated spaghetti code with object hierarchies; when it was never justified.

Total rubbish statement. But whatever works for you

EDIT: Not dissing FP and its virtues. Dismissing OOP out of hand is holier than thou. Using an example where an OOP project is converted to FP is an irrelevant metric of why FP is 'better than' XYZ.
 
Last edited:

freddster

Expert Member
Joined
Dec 13, 2013
Messages
2,470
"Most programmers" are idiots/drones trying to churn out as much code per hour to satisfy their overlords.

Any programmer worth their salt will and CAN read OOP code perfectly without getting confused.

Now, are there programmers who totally go insane in OOP and overcomplicate things? yes.

Because there are so many fly-by-night "I can code cuz I can reed gud" making money out of people with no technical knowledge, when you take over their code you hope to G-d that it's procedural in a semi-coherent form

:D 1 of the systems I worked on had 11 levels of inheritance...
Agree with spacerat. Everything has a time and place. If you're going to have lots of functionality that will be reused or it similar in fucntion with then use inheritance, overloading etc.
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
:D 1 of the systems I worked on had 11 levels of inheritance...
Agree with spacerat. Everything has a time and place. If you're going to have lots of functionality that will be reused or it similar in fucntion with then use inheritance, overloading etc.

I take it you've never been exposed to a FP enabling language; reusability is far easier to achieve without all that OOPism
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Your opinion dude
Not just mine; SA is behind the time on this one.

Total rubbish statement. But whatever works for you

EDIT: Not dissing FP and its virtues. Dismissing OOP out of hand is holier than thou. Using an example where an OOP project is converted to FP is an irrelevant metric of why FP is 'better than' XYZ.
Well you can always quote the multitude of examples where the FP community is wrong. Btw what language are you referring to (re your FP, experience)?
 

Thor

Honorary Master
Joined
Jun 5, 2014
Messages
44,236
Now I want to spit on laravel for forcing OOP into my brain. Granted I have not used it so much so OOP is not in my blood yet :twisted:
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Now I want to spit on laravel for forcing OOP into my brain. Granted I have not used it so much so OOP is not in my blood yet :twisted:
As cguy implied, and I tried to express in my first post; it's far more important that code is easier to navigate and understand.

Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious. -- Fred Brooks

Btw Hope you liked the few FP examples.
 

freddster

Expert Member
Joined
Dec 13, 2013
Messages
2,470
[)roi(];18161787 said:
I take it you've never been exposed to a FP enabling language; reusability is far easier to achieve without all that OOPism

Nope, this was 7 years ago. Just to understand all those layers was a mission in the beginning. :sick:
 

Thor

Honorary Master
Joined
Jun 5, 2014
Messages
44,236
[)roi(];18162699 said:
As cguy implied, and I tried to express in my first post; it's far more important that code is easier to navigate and understand.



Btw Hope you liked the few FP examples.

Oh yes I did, that gave me a glimpse I like the functional approach although again I am not there yet to get all philosophical but from what I can see it would appear my current way would probably be considered imperative as I have every fcking loop in the box I understand loops so I use it more than is probably appropriate I guess and looking at your examples one thing seems to stand out for me immutability almost like you don't use variables but rater constants wherever you can which means my loops won't work for shiat in the functional approach ( I think? I can be horidly wrong here)

I think what I am trying to say is Thor's current way vs Driod's way would come down to iterations vs recursions I hope that makes sense, ie I think currently I fall under the iterations way where as functional programing would be considered more recursive?
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Oh yes we indeed that gave a glimpse I like the functional approach although again I am not there yet to get all philosophical but from what I can see it would appear my current way would probably be considered imperative as I have every fcking loop in the box I understand loops so I use it more than is probably appropriate I guess and looking at your examples one thing seems to stand out for me immutability almost like you don't use variables but rater constants wherever you can which means my loops won't work for shiat in the functional approach ( I think? I can be horidly wrong here)

I think what I am trying to say is Thor's current way vs Driod's way would come down to iterations vs recessions I hope that makes sense, ie I think currently I fall under the iterations way where as functional programing would be considered more recursive?
In a way; FP is not restricted to head/tail recursion, we even use loops; anyway before you use try to use recursion in a language, you should first check how well they deal with tail/head call optimisation; if not your code can easily overwhelm the call stack == stackoverflow

Switching over to FP is a gradual process (and it's quite normal to mix paradigms). FP is a huge paradigm shift with many aspects that will take time to understand; I still struggle to get my head around a lot of these. FYI There's a joke in the FP community that monads are cursed, because once you understand monads for yourself you lose the ability to explain them to others.

In a basic sense collections like array are monads because they can wrap stuff; sometimes we even refer to them as burritos, because they wrap their ingredients. Natural the explanation can get much more complicated, e.g. If you can define flatMap for a type, the type is often called a monad, huh? anyway here's the code for a flatMap implementation in PHP (and yes it uses loops):
PHP:
function flat_map($collection, callable $callback)
{
    InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);
    $flattened = [];
    foreach ($collection as $index => $element) {
        $result = $callback($element, $index, $collection);
        if (is_array($result) || $result instanceof Traversable) {
            foreach ($result as $item) {
                $flattened[] = $item;
            }
        } elseif ($result !== null) {
            $flattened[] = $result;
        }
    }
    return $flattened;
}
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Sorry, levels of inheritance.
Yeah it always a brainf..k for me re I tend to move relatively frequently between codebases (different customers, not all OOP is equal); some just deserve a rewrite (euthanasia is the only option).
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
@Thor187

I thought it might be useful to help explain flatmap by example, specifically why it's important? Let's say we have a multi dimension array where some elements could resolve to nil(null) or to values, for example:
  • Lets' s say we have the following input: [[a, b], [c, d], [e, f], [g, h]]
Now let's say we want to adjust the values with some code (e.g. value * 2), and then return the result as a 1 dimensional array of resulting values. Let's also say that b, d, g will in the process resolve to nil(null), and the rest of the elements will resolve as follows a = 4, c = 8, e = 12, f = 14, h = 16
  • The result after all of this the result will be [8, 16, 24, 28, 32]
So to summarise Flatmap (in this case) works on an array (a collection), and can not only transform the values with a callback function (lines of code that you use transform the value), but also to discards the nil elements, and finally flattens the array. Map is almost the same, except it doesn't discard nil or flatten the array.

In FP we make extensive use of Higher Functions like map, flatmap, reduce, ... (there are many more). These functions are specifically adapted to work with the types that they are built around, for example: in FP languages there is a notion of a Optional type; it is either empty or it carries a value. Optional types replace the need for the "if (x != nil) { }" checks that you find littered in OOP code, for example:
Code:
// In OOP before working with an instance, we have to check if it's not nil
if (x != nil) { 
  x.dofunc();
}


// In FP we simply do this. 
x?.dofunc() // it only runs if x is not nil.

// The method is only excused it's it has a value / instance. 
// The operator ? is a wrapper for flatmap, the operator naturally
// varies by FP language, but the purpose is the same.
// Simple, but it's really powerful when chained together.
Why I mentioned the Optional type is that it's a perfect example of a monad; flatmap operates on it, and it wraps a something (value or nil).

This is why in FP you don't need as many loops; because the common functionality is already built into FP's higher order functions, ...and where it's missing, you can build your own.
 
Last edited:

Thor

Honorary Master
Joined
Jun 5, 2014
Messages
44,236
That's makes a hell of a lot more sense. I've done some reading as well and it's very clear to see that FP is efficient and appears a lot more streamlined it won't be hard to find your way around and it feels a bit more logically structured (the examples I've seen I'm fully aware this can go deep way beyond what my mind can fathom at this point in time)

I am going to buy myself a book or two this weekend on programming theory if there is such a thing the aim is I want to understand why I do what I do that way I'll be able to get into that optimize and refractioning stages.

Right now I just use my brain and make the code do what I think is right, but I don't have a foundation I don't have the history to know why it is being done the way it is done.

Then I can understand why in my timer

This:

PHP:
<?php
  // passing by reference
  function  computeValue( &$param ){
  // Something goes here
  foreach( $param as $k => $value){
    $param[$k] = $value + 1;
  }
  }
  $x = array();
  for( $i =0; $i<99; $i++){
    $x[$i] = $i;
  }
  computeValue( $x);
  
  // array with 100 elements each incremented by 1
  print_r( $x );

?>

Is faster, than this:

PHP:
 <?php
  // passing by value
    function  computeValue( $param ){
      // Something goes here
      foreach( $param as $k => $value){
      $param[$k] = $value + 1;
      }
      
      return $param;
    }
    $x = array();
    for( $i =0; $i<99; $i++){
      $x[$i] = $i;
    }
// array with 100 elements each incremented by 1
    print_r(computeValue( $x));
    
  ?>
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Ok here's a comparison of your two examples (option 1 & 2), against a pure functional one I created (option3), and another using hybrid foreach(option4):

PHP:
<?php

function option1()
{
	// passing by reference
	function  computeValue( &$param )
	{
		// Something goes here
		foreach( $param as $k => $value)
		{
	    	$param[$k] = $value + 1;
	    }
  }
  $x = array();
  for( $i =0; $i<99; $i++){
    $x[$i] = $i;
  }
  computeValue($x);
  
  // array with 100 elements each incremented by 1
  print join(", ", $x ) . "\n";
}

function option2()
{
	// passing by value
    function computeValue2($param) 
    {
      // Something goes here
      foreach( $param as $k => $value)
      {
      	$param[$k] = $value + 1;
      }
      
      return $param;
    }

    $x = array();
    for( $i =0; $i<99; $i++){
      $x[$i] = $i;
    }
	// array with 100 elements each incremented by 1
    print join(", ", computeValue2($x)) . "\n";
}

function option3a()
{
	function add($value)
	{
		return $value + 1;
	}
	print join(", ", array_map('add', range(0, 98))) . "\n"; 
}

function option3b()
{
	print join(", ", array_map(function($v) { return $v + 1; }, range(0, 98))) . "\n"; 
}

function option4()
{
	$x = array();
	foreach(range(0, 98) as $value)
	{
		array_push($x, $value + 1);
	}
	print join(", ", $x) . "\n";
}

function measure($function, $title) 
{
	$start = microtime(true);
	$function();
	$time_elapsed_secs = microtime(true) - $start;
	printf("%s: completed in %.6f seconds\n", $title, $time_elapsed_secs);
}

measure(option1, 'option1');
measure(option2, 'option2');
measure(option3a, 'option3a');
measure(option3b, 'option3b');
measure(option4, 'option4');
?>
Results are as follows:
Code:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
option1: completed in 0.000084 seconds
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
option2: completed in 0.000084 seconds
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
option3a: completed in 0.000074 seconds
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
option3b: completed in 0.000038 seconds
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
option4: completed in 0.000067 seconds

Now let's just for comparison compare that to a Swift LLVM compiled FP version.
Code:
print((0..<99).map { String($0 + 1) }.joined(separator: ", "))
Swift result:
Code:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
swift duration: 0.0000017006 seconds

The take away from this should hopefully be that whilst you could theoretically write faster imperative code; FP delivers a decent result against imperative code + the bonus is that's its far less code. Secondly don't always assume imperative code is going to deliver bad performance; performance is really a measure of how you write your code.

FYI In Swift like C++ and C we can occasionally improve on this by directly initialising and manipulating memory (php not so), but in practice there are very rare occasions when you'd actually benefit. In this case it's really not worth the bother.

Update: Here's a book on Functional Programming in PHP; appears to be good; most reports indicate he explains the concepts in a way that is easy to understand.

Also have a looked at these github repos
 
Last edited:

Thor

Honorary Master
Joined
Jun 5, 2014
Messages
44,236
Eyes and mind opened.

I'd like to buy all you guys a beer one weekend really. I learned more here in the past week than I did at varsity.
 

rward

Senior Member
Joined
Oct 26, 2007
Messages
865
I've found that it's mostly about trade-offs.

The trade off to this is how readable is the code to 90% of people writing and maintaining php and is having the readability knock worth the 0.00005 second saving?
If you're in something really time sensitive or getting a high number of executions a second then yes, it is worth it but if you're writing a web service for something "not too popular" that in future may be maintained by someone else, then you probably want to write it out or at least comment it nicely.

Sometimes being clever isn't clever and Keeping it Simple is best.

Use functional programming where needed, use OOP where needed and use procedural where needed but be aware of how and where you're using them.

Most of all, Comment Your Code (something I don't do often enough) so the person coming after you (usually you in 3 years) knows what you were thinking, planning and doing. In that 3 years your method of thinking is probably going to have changed and you're going to be wondering why you did something in a certain way - leave clues behind so you can remeber why.
 
Top