Benefit of composition functions - php

I have four methods which alter the input and return the output.
class edit
{
function a($input) { return $input + 4; }
function b($input) { return $input - 2; }
function c($input) { return $input * 10; }
function d($input) { return $input / 8; }
}
Coincidentally these methods need to be called one after the other with the returned output from the previous as the input to the next.
We can handle this process multiple ways.
$handle = new edit();
$output = $handle->a(8);
$output = $handle->b($output);
$output = $handle->c($output);
$output = $handle->d($output);
or
create another method within the class to handle this entire procedure.
function all($input)
{
$output = $this->a($input);
$output = $this->b($output);
$output = $this->c($output);
$output = $this->d($output);
return $output;
}
$handle = new edit(8);
$handle->all();
These both achieve the same task.
However, I have recently learned about composition functions, Which is perfect for I need to achieve.
(note for the example here I have moved the methods a,b,c,d from the class and will call them as functions in a procedural manor, I have been unable to make this composition function OOP friendly, please excuse me for this.)
function compose($f,$g,$h,$i)
{
return function($x) use ($f, $g, $h, $i) { return $f($g($h($i($x)))); };
}
$comp = compose('a', 'b','c','d');
$result = $comp(8);
With all this being said, I want to know the benefit of achieving this task with the composition function?
I can only notice minimal improvement in that we do not have to pass the input four times, only once.
In my recent research, I have come across multiple software engineers talking about how great functional programming is.
I feel that I am missing something? Or is the only improvement what I mentioned?
PS - The language I use is PHP, The methods/functions I gave here are just simple examples to illustrate the point. I am also trying to adhere to SOLID principles.
Thanks.

Related

there a more effective/elegant way to config parsing?

example:
$CONF = parse_ini_file('cfg.ini', true);
$EmailUN = $CONF['EM']['key01'];
$EmailPW = $CONF['EM']['key02'];
$EmailTO = $CONF['EM']['key03'];
$SMSAPI = $CONF['SMS']['key01'];
$SMSUN = $CONF['SMS']['key02'];
$SMSPW = $CONF['SMS']['key03'];
$SMSNUM = $CONF['SMS']['key04'];
is there a more effective/elegant way to import this data? i want to learn best practices while im still learning. i dont want to fill up the whole top of my php doc with objects calling for keys. if this is a duplicate i apologize in advance.
One approach would be a helper function that accesses your configuration.
If for example you wanted to access your configuration like this:
config('SMS.key01');
You could define the config function as:
function config(string $key)
{
static $config = parse_ini_file('cfg.ini', true);
$curr = $config;
foreach(explode('.', $key) as $segment) {
if(!isset($curr[$segment]) {
return null;
} else if(is_array($curr[$segment])) {
$curr = $curr[$segment];
continue;
}
return $curr[$segment];
}
}
The above is a minimal example roughly based on Laravel's config and array_get helpers. Your helper function would likely need to be implemented differently in the context of your application or framework.
The main advantage of this approach is that all of the implementation details of how your configuration is stored and accessed is contained within the function. What you are doing right now bleeds low level implementation details into the rest of your code.

Reducing manual object instantiation

I am trying to learn to the Dependency Inversion Principle. Currently my code is like this
class Example {
public function __construct( $input, $output ) {
$input_handler = new InputHandler( $input );
$output_handler = new OutputHandler( $output );
$input_handler->doStuff();
$output_handler->doOtherStuff();
}
}
$input = new Input();
$output = new Output();
$example = new Example( $input, $output)
However, it seems using basic dependency injection, it should be more like this?
class Example {
public function __construct( $input_handler, $output_handler ) {
$input_handler->doStuff();
$output_handler->doOtherStuff();
}
}
$input = new Input();
$output = new Output();
$input_handler = new InputHandler( $input );
$output_handler = new OutputHandler( $output);
$example = new Example( $input_handler, $output_handler)
Is this is correct?
I want to let the programmer choose the type of input / output to use when running the program. So with dependency injection (as far as I understand) it would look like this;
$input = new ConsoleInput();
$output = new FileOutput();
$input_handler = new ConsoleInputHandler( $input );
$output_handler = new FileOutputHandler( $output);
$example = new Example( $input_handler, $output_handler);
$example->doStuffToOutput();
However, I would prefer to make the programmers life a little easier by only needing to pass in the type of input and output, and not need to worry about the classes handling them;
$input = new ConsoleInput();
$output = new FileOutput();
$example = new Example( $input, $output );
$example->doStuffToOutput();
or even
$example = new Example( new ConsoleInput(), new FileOutput() );
$example->doStuffToOutput();
How can I achieve this using DIP and not end up with my initial code block? Is this a good thing to do?
While I was reading your question I felt you have two main goals. Firstly to improve the readability of your code ('..ease the programmer's life') and secondly to decouple "Example" class from the I/O handlers. For my point of view, DI is just a principle to follow in order to reach your goals.
Before I'm attaching any code, I want to emphasize that sometimes it is better to actually couple your code. Code must be coupled somehow. Do not use DI everywhere just because it has been said. Simplicity, as being described with the KISS and YAGNI principles, is always the winner.
So the big question here is whether your second goal (decoupling with DI) is the smart thing to do. Is there a real reason for the InputHandler / OutputHandler in the "Exmaple" class to be changed? If "No" is your answer, I would recommend you to keep it inside this class intact. And "maybe in the distant future it will be profitable" doesn't really count.
However, if your handlers should be unique for each type (file, console etc.), and your decoupling would help you and other programmers to extend the platform, you can take advantage of the Factory pattern. You have several ways to implement this pattern (static / abstract / simple / method factories). The main goal is to lessen the learning curve from the client, and make the "Example" class decoupled, so that adding more types or handlers would not affect this class.
class HandlerFactory {
protected static function createInputHandler(Input $input)
{
switch ($input)
{
case is_a($input, 'FileInput'):
return new FileInputHandler($input);
case is_a($input, 'ConsoleInput'):
return new ConsoleInputHandler($input);
}
throw new \Exception('Missing Input handler');
}
protected static function createOutputHandler(Output $output)
{
switch ($output)
{
case is_a($output, 'FileOutput'):
return new FileOutputHandler($output);
case is_a($output, 'ConsoleOutput'):
return new ConsoleOutputHandler($output);
}
throw new \Exception('Missing Output handler');
}
public static function createHandler($io)
{
switch ($io)
{
case is_a($io, 'Input'):
return self::createInputHandler($io);
case is_a($io, 'Output'):
return self::createOutputHandler($io);
}
throw new \Exception('Missing I/O handler');
}
}
Now your first code in your question is still relevant with a minor twist:
class Example {
public function __construct($input, $output) {
$input_handler = HandlerFactory::createHandler($input);
$output_handler = HandlerFactory::createHandler($output);
$input_handler->doStuff();
$output_handler->doOtherStuff();
}
}
$input = new Input();
$output = new Output();
$example = new Example($input, $output);
Use an Abstract Factory class to handle the instantiation of objects needed to handle i/o. You could either inject the factory into the example class, or let the factory instantiate the objects needed and then inject those into the example class. Then you can do:
$IOFactory = new IOFactory();
$example = new Example($IOFactory::makeInputHandler($inputType), $IOFactory::makeOutputHandler($outputType));
$example->doStuffToOutput();
IOFactory takes care of instantiating input and output objects base in their specific types, and then instantiates the handlers and inject them with the input and output object. Afterwards returns the handler objects to be injected in the example object.
In your case you can choose one of many creational design patterns available. My suggestion is to go with either Factory pattern or object pool pattern.
In case of factory method pattern, you can have a class with the responsibility of creating object:
class ObjectFactory {
public InputHandler createInputHandlerObject(inputobj){
if( inputobj instanceOf ConsoleInput ) {
return new ConsoleInputHandler();
} else if( inputobj instanceOf FileInput ) {
}
}
// similarly create a method for creating OutputHandler object.
//create the appropriate object by using instanceOf operator.
Since I'm familiar with Java i have given example in Java . you can change the syntax and use accordingly. This is not the only way to implement Factory Pattern.
If you want to remove the burden of creating the object at runtime you can use Object pool pattern. Hybrid of prototype pattern also becomes handy in your csse.

Best practice for tiny code reuse in PHP

For a long time I have a problem - should I reuse small parts of code and if so, how should I do it so it would be the best practice.
What I mean about small code is for example:
if (!is_array($table)) {
$table = array($table);
}
or
$x = explode("\n", $file_content);
$lines = array();
for ($i=0, $c = count($x); $i<$c; ++$i) {
$x[$i] = trim($x[$i]);
if ($x[$i] == '') {
continue;
}
$lines[] = $x[$i];
}
Such tiny parts of code may be used in many classes in one project but some of them are used also in many projects.
There are many possible solutions I think:
create simple function file and put them all reusable piece of codes as function, include them simple in project and use them whenever I want
create traits for those piece of codes and use them in classes
reuse code by simple copy paste or creating function in specific class (??)
other ?
I think all of those solutions have their pros and cons.
Question: What method should I use (if any) to reuse such code and why is this approach the best one in your opinion?
I think that "the best way" depends on many factors including the technology your applications use (procedural, OOP), versions of PHP they run on, etc. For example, traits are interesting and useful but they are available only since php 5.4.0 so using this tool to group your code snippets you will not be able to reuse them in systems running on earlier PHP versions. On the other hand if your app uses an OOP style and you organized your resuable small code snippets in functions, their usage may seem awkward in an OOP app and conflict with the function names in a particular class. In this case I think grouping your functions in classes would seem more natural.
Putting everything together, it seems that classes provide better tool for grouping resuable code snippets in terms outline above, namely backward compatibility with earlier PHP versions, avoiding function names conflicts, etc.) Personally I code mostly in OOP, so i have a Util class where I group small functions representing resuable pieces of code snippets that do not directly relate to each other and thus could not be logically groupped in other classes.
As mentioned already traits are a good thing. But might be a bit hard to manage after a while, and it might not be supported everywhere since its new.
What I do is to create Tool classes that have a lot small static functions, like:
class ArrayTools
{
static public function CheckArray($array)
{
if (!is_array($array))
{
$array = array($array);
}
return $array;
}
}
So you can call it with ArrayTools::CheckArray($array)
Please go with traits if your code mainly involves classes and objects.. As the the concept of traits exclusively focusses on code reuse ability.
Following are the code snippets which actually I use with Plain PHP projects, these code snippets are used from various frameworks good traits and best practices.
1.
The following code is used to check the environment in which your working, based on the environment you can set the some global variables, error reporting as so on.
if(!defined('ENVIRONMENT')){
define('ENVIRONMENT','DEVELOPMENT');
}
if (defined('ENVIRONMENT'))
{
switch (ENVIRONMENT)
{
case 'DEVELOPMENT':
case 'TESTING':
$base_url = 'http://localhost/project_name/';
error_reporting(E_ALL);
break;
case 'PRODUCTION':
$base_url = 'http://hostname/project_name/';
error_reporting(0);
break;
default:
exit('The application environment is not set correctly.');
}
}
2.
/* This function is used to PRINT the ARRAY data in the pre formatted manner */
if (!function_exists('pr')) {
function pr($data) {
echo '<pre>', print_r($data), '</pre>';
}
}
3.
/* This function is used to Sanitize the user data and make data safe to insert into the database */
function sanitize($data) {
global $link;
$data = trim($data);
return htmlentities(strip_tags(mysqli_real_escape_string($link, $data)));
}
4.
/* Used to get the difference of 2 arrays
Returns the array with difference
*/
function multi_diff($arr1,$arr2){
$result = array();
foreach ($arr1 as $k=>$v){
if(!isset($arr2[$k])){
$result[$k] = $v;
} else {
if(is_array($v) && is_array($arr2[$k])){
$diff = multi_diff($v, $arr2[$k]);
if(!empty($diff))
$result[$k] = $diff;
}
}
}
return $result;
}
5.
/* This fnction is used to generate the random keys of specific length
Accepts parameter of certain length if not specified it will generate 20 bit length automatically
*/
function generate_random_key($length = 20) {
//Initializing the varialble
$keystring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
$random_key = '';
for ($i = 0; $i < $length; $i++) {
$random_key.=$keystring[rand(0, strlen($keystring) - 1)];
}
//Return the randomly generated key
return $random_key;
}
6.
/* This function outputs the errors in ul>li format with unstyled
* To get the bullets styling remove class='list-unstyled' in <ul> tag */
function output_errors($errors){
$output = array();
foreach ($errors as $error) {
$output[] = '<li>'.$error.'</li>';
}
return '<ul class="list-unstyled">'.implode('', $output).'</ul>';
}
7.
/* Checks whether the user is loggedin else will redirect to the protectect page */
function protected_page(){
if(is_loggedin() === false){
// header('Location: protected.php');
header('Location: logout.php');
exit();
}
}
8.
/* If user tries to access the page directly accessing through the URL,
* If already loggedin then redirect him to any of the inner page
*/
function login_redirect(){
if(is_loggedin() === true){
header('Location: home.php');
}
}
9.
/* This function is used to check whether the user exists or not */
function email_exists($email){
/* Your Code */
}
/* This function is used to check whether the user isActive or not */
function is_active($email){
/* Your Code */
}
/* This function will get the userid from the email */
function userid_from_email($email) {
/* Your Code */
}
/* This fucntion is used to login the user based on the email-id and password */
function login($email,$password){
/* Your Code */
}
/* Check whether the USER is loggedin or not */
function is_loggedin(){
return (isset($_SESSION['userid'])) ? true : false;
}
Hope this helps you. Cheers!

Can temporary functions/macros be created in PHP?

Take a look at the following illustration:
// Trims input, fixes spaces and encodes bad glyphs. Also works with arrays.
function prepare_param($param)
{
$retval = "";
function prc($param)
{
$r = split(" ", trim($param));
foreach($r as $i => $e)
$r[$i] = urlencode($e);
return join("+", $r);
}
// If input is an array
if(is_array($param))
{
$retval = array();
foreach($param as $e)
$retval[] = prc($e);
}
// If input is a string
else if(is_string($param))
{
return prc($param);
}
else throw new Exception("Invalid input! Expected String or Array.");
}
Obviously the function prc will now be declared globally, even though declared inside a function. Is there a way to follow this principle, creating a tiny function/macro inside another function as not to litter the global scope? The alternative would be to make a class with a private function, which seems like overkill for my use.
Any help appreciated
You probably want closures, which are anonymous functions.
If you have PHP 5.3, enter anonymous functions:
$prc = function($param)
{
$r = split(" ", trim($param));
foreach($r as $i => $e)
$r[$i] = urlencode($e);
return join("+", $r);
};
if(is_array($param))
{
$retval = array();
foreach($param as $e)
$retval[] = $prc($e);
}
else if(is_string($param))
{
return $prc($param);
}
In this case, $prc only lives in the scope of your prepare_param() function.
If you have access to >=PHP 5.3, you can use anonymous functions, and if not, you can use create_function.
If you don't have PHP 5.3, you can use the create_function function.
There are two ways to do so. The closures/anonymous functions are possible from PHP 5.3, and the oldschool way would be to use create_function() - which is quite fugly.
However in your case, you don't want either. There is no benefit in creating or recreating the function. You just need it once, as it does not depend on any initialization state. The idiom you should use is called "dererred definition" and possible in PHP with:
if (!function_exists("prc")) {
function prc($param) {
...
}
}
You should name it with its parent function as prefix however (e.g. prepare__prc) to avoid clashes and to signalize its internal use.
Oh, and btw it could also be simplified compacted into:
$param = join("+", array_map("urlencode", split(" ", trim($param))));
anonymous functions might be what you are looking for
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
If you don't use php 5.3 please be aware of the fact that the memory allocated by the "create_function()" function isn't released until the php process finishes. So if you create a lot of functions you might be running into issues.

How to alias a function in PHP?

Is it possible to alias a function with a different name in PHP? Suppose we have a function with the name sleep. Is there a way to make an alias called wait?
By now I'm doing like this:
function wait( $seconds ) {
sleep($seconds);
}
Until PHP 5.5
yup, function wait ($seconds) { sleep($seconds); } is the way to go. But if you are worried about having to change wait() should you change the number of parameters for sleep() then you might want to do the following instead:
function wait() {
return call_user_func_array("sleep", func_get_args());
}
PHP 5.6+ only
Starting with PHP 5.6 it is possible to alias a function by importing it:
use function sleep as wait;
There's also an example in the documentation (see "aliasing a function").
Nope, but you can do this:
$wait = 'sleep';
$wait($seconds);
This way you also resolve arguments-number-issues
You can look at lambdas also if you have PHP 5.3
$wait = function($v) { return sleep($v); };
If you aren't concerned with using PHP's "eval" instruction (which a lot of folks have a real problem with, but I do not), then you can use something like this:
function func_alias($target, $original) {
eval("function $target() { \$args = func_get_args(); return call_user_func_array('$original', \$args); }");
}
I used it in some simple tests, and it seemed to work fairly well. Here is an example:
function hello($recipient) {
echo "Hello, $recipient\n";
}
function helloMars() {
hello('Mars');
}
func_alias('greeting', 'hello');
func_alias('greetingMars', 'helloMars');
greeting('World');
greetingMars();
No, there's no quick way to do this in PHP. The language does not offer the ability to alias functions without writing a wrapper function.
If you really really really needed this, you could write a PHP extension that would do this for you. However, to use the extension you'd need to compile your extension and configure PHP to us this extension, which means the portability of your application would be greatly reduced.
No, functions aren't 1st-class citizens so there's no wait = sleep like Javascript for example. You basically have to do what you put in your question:
function wait ($seconds) { sleep($seconds); }
you can use runkit extension
http://us.php.net/manual/en/function.runkit-function-copy.php
function alias($function)
{
return function (/* *args */) use ($function){
return call_user_func_array( $function, func_get_args() );
};
}
$uppercase = alias('strtoupper');
$wait = alias('sleep');
echo $uppercase('hello!'); // -> 'HELLO!'
$wait(1); // -> …
If your PHP doesn't support use x as y syntax, in older PHP version you can define anonymous function:
$wait = create_function('$seconds', 'sleep($seconds);');
$wait(1);
Or place the code inside the constant, e.g.:
define('wait', 'sleep(1);');
eval(wait);
See also: What can I use instead of eval()?
This is especially useful if you've long piece of code, and you don't want to repeat it or the code is not useful for a new function either.
There is also function posted by Dave H which is very useful for creating an alias of a user function:
function create_function_alias($function_name, $alias_name)
{
if(function_exists($alias_name))
return false;
$rf = new ReflectionFunction($function_name);
$fproto = $alias_name.'(';
$fcall = $function_name.'(';
$need_comma = false;
foreach($rf->getParameters() as $param)
{
if($need_comma)
{
$fproto .= ',';
$fcall .= ',';
}
$fproto .= '$'.$param->getName();
$fcall .= '$'.$param->getName();
if($param->isOptional() && $param->isDefaultValueAvailable())
{
$val = $param->getDefaultValue();
if(is_string($val))
$val = "'$val'";
$fproto .= ' = '.$val;
}
$need_comma = true;
}
$fproto .= ')';
$fcall .= ')';
$f = "function $fproto".PHP_EOL;
$f .= '{return '.$fcall.';}';
eval($f);
return true;
}
nope. the way you wrote is the best way to do it.
No, there's no quick way to do so - at least for anything before PHP v5.3, and it's not a particularly good idea to do so either. It simply complicates matters.
Since PHP 5.6
This is especially helpful for use in classes with magic methods.
class User extends SomethingWithMagicMethods {
public function Listings(...$args) {
return $this->Children(...$args);
}
}
But I'm pretty sure it works with regular functions too.
function UserListings(...$args) {
return UserChildren(...$args);
}
Source:
PHP: New features -> "Variadic functions via ..."
I know this is old, but you can always
$wait = 'sleep';
$wait();
What I have used in my CLASS
function __call($name, $args) {
$alias['execute']=array('done','finish');
$alias['query']=array('prepare','do');
if (in_array($name,$alias['execute'])){
call_user_func_array("execute",$args);
return TRUE;
}elseif(in_array($name,$alias['query'])){
call_user_func_array("query",$args);
return TRUE;
}
die($this->_errors.' Invalid method:'.$name.PHP_EOL);
}

Categories