[HN Gopher] Functional PHP (2015)
___________________________________________________________________
Functional PHP (2015)
Author : luu
Score : 50 points
Date : 2024-10-13 05:25 UTC (16 hours ago)
(HTM) web link (fluffyandflakey.blog)
(TXT) w3m dump (fluffyandflakey.blog)
| sourcecodeplz wrote:
| I've tried Node when the trend started and it was okay. But the
| problem was that the actual script was also the server. So if the
| script hanged, the whole server hanged. Went back to PHP and
| never looked back.
| ec109685 wrote:
| php has the opposite problem where if a script hangs on io, you
| can be cooked (assuming other requests blocked similarly).
|
| Different trade offs for sure, but given IO is often the
| bottleneck, having it force you to think about running code
| asynchronously can often result in code that runs more in
| parallel than equivalent first blush php code.
|
| For instance, if you were writing in a function style a program
| that fetched entries from a web service, for each of those
| results, run a summarization pass using another service, and
| then insert summarization result in a database, a style like
| shown in this article might serialize the summarization /
| insert operations, one after the other, where you'd instead
| want each result to be processed in parallel.
|
| Lots of libraries in node that make that easy and the code
| straightforward to reason about.
| freedomben wrote:
| It sounds like you "tried Node" but didn't learn/read enough to
| understand the event loop architecture (and why node is
| asynchronous). Node is pretty simple (and powerful) but yes if
| you don't know about the event loop, you'll make a blocking
| call (synchronous function) and end up blocking the loop (which
| will hang your whole process).
| sourcecodeplz wrote:
| I admit, i struggled with promises, within promises, within
| promises. Synchronous, I understood and just worked for me.
| lexicality wrote:
| Not that it matters because you don't care and no one uses
| promises any more but it does really sadden me how much
| nested promise code I've found over the years.
|
| eg this function sad(input) {
| return new Promise((resolve, reject) =>
| foo(input).then((data) => {
| bar(data).then((data2) => {
| baz(data2).then(resolve, reject) })
| }) ); }
|
| could quite as easily have been written like this:
| function happy(input) { return foo(input)
| .then((data) => bar(data)) .then((data2) =>
| baz(data2)) }
|
| But no one seemed to be aware that you can return a promise
| in the `.then()` callback and have it chain neatly...
| datashaman wrote:
| async functions return promises. everyone uses promises.
| MrJohz wrote:
| One of the rules I teach people when they're starting
| using promises is never ever to write `new Promise(...)`.
|
| That's not because it's bad - it's a useful tool if
| you're connecting event or callback-based systems to the
| world of promises and async/await. But a lot of people
| who are just getting started with promises seem to take a
| while to get used to chaining, and often resort to using
| the `new Promise` constructor to get promises to appear
| in the places they expect. So giving them a blanket rule
| ("never use `new Promise`") forces them to figure out a
| different approach.
|
| It's become a lot easier since the introduction of
| async/await, where chaining isn't so important, but there
| are still always times when you need to understand that
| underneath the syntax sugar, there's still promises
| happening, and so I'm still finding the rule useful.
| Aurel300 wrote:
| That's not inherent to PHP, but rather the ecosystem it's
| usually used in. The standard "LAMP" stack, for example, has
| Apache in it for the actual server, talking to PHP using a CGI
| interface. So if your PHP script crashes or hangs, the server
| itself is still up, and capable of serving other clients.
|
| If you set up a Node script where e.g. Express talks directly
| to the clients, then yes, the script crashing or hanging means
| the server becomes unavailable or unresponsive. However, you
| can also set up a layer in front of Node. See cgi-node for
| replicating the CGI workflow you might be used to.
|
| There are some advantages to the standard Node model though:
| the program can manage its own resources, such as keeping a
| database connection open; it can run asynchronous maintenance
| tasks; it can see and report the current server load; it can
| easily combine HTTP(S) communication and Web socket streams;
| etc.
| sgdfhijfgsdfgds wrote:
| > The standard "LAMP" stack, for example, has Apache in it
| for the actual server, talking to PHP using a CGI interface.
| So if your PHP script crashes or hangs, the server itself is
| still up, and capable of serving other clients.
|
| Not exactly... the standard, typical LAMP stack makes use of
| mod_php, so the PHP engine is in-process with one of the
| Apache process.
|
| The fact that Apache has multiprocess/hybrid workers is
| actually why the server stays up and can serve more requests.
|
| Some contemporary LAMP stacks use FPM, I guess; most of those
| in shared hosting ISPs for example because of the possibility
| of running the script as a user process.
| BirAdam wrote:
| I would imagine that FPM is more common than people realize
| because it's also usually faster, and running scripts as a
| separate user is more secure. For example, if PHP is a user
| with read-only access to the document root, it is far more
| difficult for an attacker to do file injection.
| anon7000 wrote:
| I mean, there are tradeoffs with both approaches. It seems to
| me that Node's stateful approach is used by other web servers
| and languages too.
|
| The main tradeoff is you're now reloading the entire server for
| every request in PHP. If you have a massive server or
| framework, that might not be the fastest thing in the world.
| debacle wrote:
| This is one of the most underrated features of PHP.
| hipadev23 wrote:
| You can make this same mistake in PHP blocking operations with
| 1 worker process in mod_php, php-fpm, or handling sockets
| directly. The fix is pretty standard: run multiple processes,
| threads, or use non-blocking operations.
|
| The most common PHP setups are simply running multiple
| processes behind a httpd daemon, so this problem is less
| frequently encountered. But it's still lurking at a certain
| concurrency level.
| skrebbel wrote:
| (2015)
|
| Btw while this code doesn't win a prize, I agree with the author
| that functional style is worth it in many cases, even for a
| language as wordy and cumbersome as PHP. I still love PHP - its
| deployment story is still unparalleled and its standard library
| came batteries included since forever.
| ec109685 wrote:
| php with lambdas eliminates a bunch of the syntax and can let
| map/reduce style code be colocated while still achieving the
| functional style benefits.
|
| A big issue though (at least for some apps), is there is no
| attempt to make that code parallelized for the io parts. So if
| you aren't careful, you can end up with n+1 style IO calls,
| making things very slow.
| skrebbel wrote:
| Personally I consider that a benefit at least as often as
| not. In Nystromian terms, PHP functions are colorless, and
| that removes a whole kind of complexity (at the cost of, like
| you correctly point out, potential performance problems).
| chx wrote:
| tl;dr: Hardware is cheap. Engineers are expensive.
|
| > Instead of fearing the overhead in PHP for function calls,
|
| Already in 2015 in almost all applications this is a premature
| optimization which is rightly known as the root of all evil.
| Please. Your app will talk to the network, likely run a database
| query which is like thousands or millions of times slower than a
| function call. Further, even if there is a measurable difference
| the cost of hardware which makes that difference go away is very
| likely to be smaller and much smaller at that than the cost of
| the engineering hours wasted during maintenance when wrestling
| with code which was written with a "function calls are expensive"
| mindset.
|
| This doesn't mean you don't need to worry about performance and
| scalability but even that is going to be much easier if you have
| a well structured code.
| ec109685 wrote:
| IO has a very different cost than wasting CPU cycles, so
| shouldn't necessarily be lumped together when analyzing
| tradeoffs.
|
| Your point still stands that fundamentally changing the design
| of code should limited to the hottest parts.
|
| Probably the biggest risk to this style map/reduce code is that
| you end up having IO deeply nested running synchronously versus
| grouping operations that can be run in parallel.
| juangacovas wrote:
| Well, in my particular experience with juniors, it's
| astonishing the so many ways they have to make any code run
| slower than it has to be (besides the network and database
| queries), just by thinking 'nah, this is a computer and it can
| do millions of ops by second'. And that's why I always take the
| "premature optimization" dogma with a grain of salt while my
| life's miserable enough having to accelerate some other's
| stuff.
| cynicalsecurity wrote:
| His code is crap, I'm not even sorry for saying this. For the
| case he is working with, OOP is absolute must.
| SoftTalker wrote:
| OOP is never an absolute must. It's a design choice, one of
| several that can be taken.
| huqedato wrote:
| OOP is a lousy joke.
| cies wrote:
| You can write OOP-style in C, FP-style in C/C++/Java or even PHP.
| Sure.
|
| Writing pure FP code (pushing all the side effects to the "edges
| of the program" in C is possible! But it's going to take a lot of
| discipline from the programmers: there is no safety-net and lots
| of dreadful boilerplate.
|
| Impracticle, but possible.
| huqedato wrote:
| writing/thinking in FP style since 2020. Elixir, Js, F#, Julia
| and even PhP. Never got back to OOP. Never needed to. I realized
| what a waste of time and frustration had been OOP for me for
| almost 15 years (Java, C#).
___________________________________________________________________
(page generated 2024-10-13 22:01 UTC)