Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

revmoo posted:

I've never seen a use case of switch() where I thought it made sense. At best you're abbreviating what should be a function or class, depending on complexity, and at worst you've written a bunch of lovely if statements that could have been done a smarter way.
There are cases where you have to have if/switch statements without some "cleaner" way to do it. For example it's useful when you'd have a bunch of if statements would only check for equality. This is common when you're dealing with types and you have to manipulate data depending on the type (which might include calling a specific function for that specific type). An example of this, I mean that your incoming data is a string, and it could represent a string, a boolean, a number, a date, etc.

The last switch statement I wrote was given a database info object, open an appropriate table factory for it. I could have written

code:
if (dbInfo.getType() == DBTypes.ORACLE) {
    // do stuff
}
else if (dbInfo.getType() == DBTypes.POSTGRES) {
    // do stuff
}
...
but it was cleaner (imo) to just make a switch:
code:
switch(dbInfo.getType()) {
    case ORACLE:
        // do stuff
        break;
    case POSTGRES:
        // do stuff
        break;
    ...
}
You definitely couldn't accomplish this through a function/class and need to rely on an if or a switch. I'm not sure why you'd say the switch is some horrible thing over the if.

Adbot
ADBOT LOVES YOU

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If you litter your code with switch statements that check which database you're interacting with, adding another supported database is suddenly difficult because now you need to find and change every switch statement, if you're trying to track down a bug specific to one database implementation you need to track down every point at which the implementations diverge, etc.. A better way of implementing it is to have a dbInfo subclass for every database you're interacting with, that encapsulates all your database specific logic - the basic interface might have a method called getTableFactory that returns something that implements the TableFactory interface, where OracleDbInfo returns an OracleTableFactory from that method, PostgresDbInfo returns a PostgresTableFactory, etc.. Then when you need to add MySql support, all you need to do is write a new dbInfo subclass that implements the appropriate functionality. This is why polymorphism is generally preferred over switch statements.

That's not to say you should never use switch statements - writing a ladder of if statements because "switch statements are bad :downs:" is cargo-cult shitfuckery at its finest. But if you find that a switch statement looks like a good tool for the job, perhaps you should consider using polymorphism instead.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Jabor posted:

If you litter your code with switch statements that check which database you're interacting with, adding another supported database is suddenly difficult because now you need to find and change every switch statement, if you're trying to track down a bug specific to one database implementation you need to track down every point at which the implementations diverge, etc.. A better way of implementing it is to have a dbInfo subclass for every database you're interacting with, that encapsulates all your database specific logic - the basic interface might have a method called getTableFactory that returns something that implements the TableFactory interface, where OracleDbInfo returns an OracleTableFactory from that method, PostgresDbInfo returns a PostgresTableFactory, etc.. Then when you need to add MySql support, all you need to do is write a new dbInfo subclass that implements the appropriate functionality. This is why polymorphism is generally preferred over switch statements.

That's not to say you should never use switch statements - writing a ladder of if statements because "switch statements are bad :downs:" is cargo-cult shitfuckery at its finest. But if you find that a switch statement looks like a good tool for the job, perhaps you should consider using polymorphism instead.
Oh yeah, if I was littering the code base with these checks sure, but there's one of these in the code base, I'm not sure creating an interface/subclasses with one function is quite worth it yet as what problem is that really fixing? You'd still just be looking at one function instead of some other function.

How about :
code:
// data = is a string coming from user input
// field is a generic container which can hold one thing of any type
switch(toType) {
    case STRING:
        field.setString(data);
        break;
    case INTEGER:
        field.setInteger(data);
        break;
    case DOUBLE:
        field.setDouble(data);
        break;
    case DATE:
        field.setDate(data);
        break;
    ...
}
How would you solve that with polymorphism?

revmoo
May 25, 2006

#basta
Oh, we're doing JS in the php thread now? :)

code:
field.setData = function(toType, data) {
    if (toType == 'STRING') this.setString(data);
    if (toType == 'INTEGER') this.setInteger(data);
    if (toType == 'DOUBLE') this.setDouble(data);
    if (toType == 'DATE') this.setDate(data);
}
field.setData(toType, data);
Excuse any glaring syntactical issues I haven't had my morning coffee yet. The reason I'd do it this way is because you can jam a ton of various conditions into the function and still fit them on a single page. Switch statements are harder to read. Notice how all the conditions are stacked right on top of each other line after line? This solution is half the line count also.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

revmoo posted:

Oh, we're doing JS in the php thread now? :)

code:
field.setData = function(toType, data) {
    if (toType == 'STRING') this.setString(data);
    if (toType == 'INTEGER') this.setInteger(data);
    if (toType == 'DOUBLE') this.setDouble(data);
    if (toType == 'DATE') this.setDate(data);
}
field.setData(toType, data);
Excuse any glaring syntactical issues I haven't had my morning coffee yet. The reason I'd do it this way is because you can jam a ton of various conditions into the function and still fit them on a single page. Switch statements are harder to read. Notice how all the conditions are stacked right on top of each other line after line? This solution is half the line count also.
I'm going to assume you meant to use else ifs and not just if statements?

It was actually Java, but you could apply the same ideas to PHP with constants:
code:
// $data = is a string coming from user input
// $field is a generic container which can hold one thing of any type
switch($toType) {
    case Types::STRING:
        field.setString($data);
        break;
    case Types::INTEGER:
        field.setInteger($data);
        break;
    case Types::DOUBLE:
        field.setDouble($data);
        break;
    case Types::DATE:
        field.setDate($data);
        break;
    ...
}
I personally hate the way you've written your if statements and think that the switch is cleaner to read overall. It's a style thing really, and the same argument of "I don't see any good use cases" for shooting down ever using a switch could be applied to any other style thing (like tabs/spaces, etc.).

revmoo
May 25, 2006

#basta

Master_Odin posted:

I personally hate the way you've written your if statements and think that the switch is cleaner to read overall.

This is the crux of the issue, you're making an aesthetic argument and that's going to boil down to personal preference. Personally I like being able to see 150+ conditionals on a single page of my coding monitor, and switch statements eat up line counts like crazy.

I'd love to see a technical argument in favor of switch statements, though. They seem really popular among C developers, but that's probably a result of the lack of OOP.


vvv Good one!

revmoo fucked around with this message at 20:04 on Mar 7, 2015

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

revmoo posted:

This is the crux of the issue, you're making an aesthetic argument and that's going to boil down to personal preference. Personally I like being able to see 150+ conditionals on a single page of my coding monitor, and switch statements eat up line counts like crazy.

I'd love to see a technical argument in favor of switch statements, though. They seem really popular among C developers, but that's probably a result of the lack of OOP.
It's more efficient to use a switch in compiled languages and will give you some runtime speed improvement. Especially if you have 150+ conditionals.

http://stackoverflow.com/questions/395618/is-there-any-significant-difference-between-using-if-else-and-switch-case-in-c

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Master_Odin posted:

How about :
code:
// data = is a string coming from user input
// field is a generic container which can hold one thing of any type
switch(toType) {
    case STRING:
        field.setString(data);
        break;
    case INTEGER:
        field.setInteger(data);
        break;
    case DOUBLE:
        field.setDouble(data);
        break;
    case DATE:
        field.setDate(data);
        break;
    ...
}
How would you solve that with polymorphism?

The overall architecture here is straight-up wonky, it's hard to offer suggestions beyond "rewrite the whole thing to fix some of the worst bits". Where does toType come from? What is the point of the field class anyway?

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
What have I done? :negative:

Personally I was arguing more that switch statements aren't a good choice for high-level flow control. I'm really only inclined to use them where there's one value comparison occurring, and I'm pretty certain there's nothing else that's going to factor in.

I hate seeing this:
php:
<?
public function myEditAction(Request $request)
{
    switch($request->get('mode') {
        case 'edit':
            // Tons of poo poo
            break;
        case 'publish':
            // Tons of other poo poo
            break;
    }
}
?>
Because there might be other conditions surrounding if the publish mode should be stepped in to. Refactoring out a switch() statement also means you have to get rid of all the logic associated with the switch - the statement, all instances of "case", and you need to understand all the code within the switch, because there might be a break; half way through a thousand lines of code.

This is fine:
php:
<?
public function annoyMyThing($thing, $annoyType)
{
    switch($annoyType) {
        case self::ANNOY_TYPE_GENTLE:
        case self::ANNOY_TYPE_MEDIUM: // deprecated
            $thing->poke();
            break;
        case self::ANNOY_TYPE_VIOLENT:
        default:
            $thing->slap();
            break;
    }
}
?>
I see this poo poo in Symfony, and I'm not a big fan of it either:
php:
<?
    switch(true) {
        case ($myThing->getThing() == $anotherBit->getBit()):
        case ($myThing->getThing() == $something->getThing()):
            $myThing->derp();
            break;
        case: ($something->getThing() != $what):
        default:
            $myThing->flap();
            break;
    }
?>
But that arose because people found it was OK to do this:
php:
<?
switch(true) {
    case ($x instanceof MyClass):
    case ($x instanceof AnotherClass):
        $x->doSomething();
        break;
    case ($x instanceof CrapClass):
        $x->doCrap();
        break;
    default:
       throw new RuntimeException('eh?);
}
?>
There's no hard and fast rule, but my argument is mostly not to wrap what could turn into shitloads of code in a switch, because if you have to refactor it away, it's a giant pain in the rear end.
What's the likelihood of needing to refactoring it? That's entirely down to where in your code it lives, and what it's doing.

Experto Crede
Aug 19, 2008

Keep on Truckin'
What's a recommended resource for learning about Object Oriented PHP? I'm having a bit of trouble wrapping my head around it compared to procedural style.

Lots of results on google, but specific suggestions from people who have used them would be appreciated

jony neuemonic
Nov 13, 2009

Experto Crede posted:

What's a recommended resource for learning about Object Oriented PHP? I'm having a bit of trouble wrapping my head around it compared to procedural style.

Lots of results on google, but specific suggestions from people who have used them would be appreciated

This is a decent overview that includes a short comparison between procedural and OO styles: http://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762

Are there specific things you're struggling with?

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
Anyone here got experience with Laravel? Opinions?

Pretty new to PHP as a whole.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Dougie McdDouger posted:

Anyone here got experience with Laravel? Opinions?

Pretty new to PHP as a whole.

It's pretty rad!

revmoo
May 25, 2006

#basta
It's the best framework for PHP at the moment (and probably for a decent while into the future)

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
RE: Laravel
Version 5 is pretty new, the docs are good and it has lots of great features.
It seems like most package providers are updating support for 5.x but most guides you find online for doing things and most packages are for 4.2.
I personally am not using 5.x yet because some dependencies are not fully supported on 5.x and the upgrade process is a PITA!

I totally recommend signing up for an account at http://laracasts.com. It's worth every penny if you're just getting started and don't want to have to learn the hard way.

Count Thrashula
Jun 1, 2003

Death is nothing compared to vindication.
Buglord
Also Laravel has great documentation and resources (e.g. Laracasts)

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
Laracast seems interesting. Do you need much prior knowledge of PHP prior to their tutorials? I'm perfectly happy with HTML, CSS. I've only done the code academy course on PHP.

revmoo
May 25, 2006

#basta

Dougie McdDouger posted:

Laracast seems interesting. Do you need much prior knowledge of PHP prior to their tutorials? I'm perfectly happy with HTML, CSS. I've only done the code academy course on PHP.

Tbh you could just jump right in as long as you have a solid theoretical understanding of MVC and ORMs/database abstraction layers and writing queries. If not, you might want to bite off some smaller pieces first.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Dougie McdDouger posted:

Laracast seems interesting. Do you need much prior knowledge of PHP prior to their tutorials? I'm perfectly happy with HTML, CSS. I've only done the code academy course on PHP.

There are some php beginner tutorials as well as some intro to OOP and MVC stuff too.

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.

revmoo posted:

Tbh you could just jump right in as long as you have a solid theoretical understanding of MVC and ORMs/database abstraction layers and writing queries. If not, you might want to bite off some smaller pieces first.

Any suggestions? That is jargon to me currently.

revmoo
May 25, 2006

#basta
Read the book 'PHP Objects, Patterns and Practice'

It won't get you all the way there but it will start you down the road. It's a great book and it dispenses with the hello world crap and jumps right in with the expectation that you know what a for loop is but you don't know what a front-controller pattern is.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

revmoo posted:

Read the book 'PHP Objects, Patterns and Practice'

It won't get you all the way there but it will start you down the road. It's a great book and it dispenses with the hello world crap and jumps right in with the expectation that you know what a for loop is but you don't know what a front-controller pattern is.

http://www.amazon.com/dp/1430260319 specifically.

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
Cool. I'm getting there slowly.

Essentially, what I'm trying to get to is something like this: https://goonauth.goonrathi.com/login but for a different website and forum (based on Xenforo).

I've also been going through some free Laracasts i've found: the fundamental lessons.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Dougie McdDouger posted:

Cool. I'm getting there slowly.

Essentially, what I'm trying to get to is something like this: https://goonauth.goonrathi.com/login but for a different website and forum (based on Xenforo).

I've also been going through some free Laracasts i've found: the fundamental lessons.

Seems it's on Github, you can easily clone this to your dev environment, run
code:
composer install
and
code:
php artisan migrate
and be on your way. You can then tear into it to see how it works and/or modify it to fit your needs.


Don't have a dev environment?
http://laravel.com/docs/5.0/homestead

Install vagrant and oracle virtual box!

Impotence
Nov 8, 2010
Lipstick Apathy
is that the hilariously overengineered goonauth that requires LDAP/AD and assigns users to OUs at auth time? iirc it's laravel 4

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.

DarkLotus posted:

Seems it's on Github, you can easily clone this to your dev environment, run
code:
composer install
and
code:
php artisan migrate
and be on your way. You can then tear into it to see how it works and/or modify it to fit your needs.


Don't have a dev environment?
http://laravel.com/docs/5.0/homestead

Install vagrant and oracle virtual box!

When I try

code:
PHP artisan migrate
I get

code:
[PDOException]                                    
  SQLSTATE[HY000] [2002] No such file or directory

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.

Biowarfare posted:

is that the hilariously overengineered goonauth that requires LDAP/AD and assigns users to OUs at auth time? iirc it's laravel 4

Ah maybe that's why I'm failing. Im trying to integrate with Laravel 5...

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Dougie McdDouger posted:

When I try

code:
PHP artisan migrate
I get

code:
[PDOException]                                    
  SQLSTATE[HY000] [2002] No such file or directory

That was a very very rough "getting started guide"
There's more involved in getting a cloned site up and running. If you need some help, hit me up on IM and I can clone it in my dev environment and see what steps need to be taken to get it working.

Impotence
Nov 8, 2010
Lipstick Apathy
i would assume you didnt fill in app/config/database.php and you didnt copy app/config/goonauth-sample.php to app/config/goonauth.php and configure your LDAP server appropriately

DimpledChad
May 14, 2002
Rigging elections since '87.
This might be overkill for someone just getting started out, but if you really want to develop a deep understanding of OOP best practices, software architecture, and the design process, I highly recommend the book Code Complete by Steve McConnell. It is easily digestible in small chunks - each chapter focuses on a different topic, and is fairly self contained, so you can learn a lot without reading the whole book from cover to cover - and it has one of the best balances of theory and nuts-and-bolts pragmatism I've seen. The examples are in Java, C++ and VB, but if you're writing OO PHP the concepts should transfer almost 100%. It's one of the best and most comprehensive "bibles" out there for software development in general and the OO approach in particular.

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
Working on getting my PHP fundamentals solid first.

But this is baffling me right now.

code:
	<?php
	$flipCount = 0;
	do {
		$flip = rand(0,1);
		$flipCount ++;
		if ($flip){
			echo "<p>H</p>";
		}
		else {
			echo "<p>T</p>";
		}
	} while ($flip);
	$verb = "were";
	$last = "flips";
	if ($flipCount == 1) {
		$verb = "was";
		$last = "flip";
	}
	echo "<p>There {$verb} {$flipCount} {$last}!</p>";
	?>
I get the do method, but I don't get the if method here.

How does the program know what $flip needs to equal to echo the html? In my head it would be like this:

code:
		if ($flip == 1){
			echo "<p>H</p>";
		}
		elseif ($flip == 0) {
			echo "<p>T</p>";
		}

YO MAMA HEAD
Sep 11, 2007

What are the possible values of $flip when it's being checked inside the conditional?

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.

YO MAMA HEAD posted:

What are the possible values of $flip when it's being checked inside the conditional?

code:
$flip = rand(0,1);

YO MAMA HEAD
Sep 11, 2007

Right, so how would if ($flip) be similar to if ($flip == 1) ?

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
I'm not sure I'm following you here sorry.

YO MAMA HEAD
Sep 11, 2007

Well, I realize it's because I got a little mixed up myself in trying to be didactic! You should get a general sense of http://php.net/manual/en/types.comparisons.php even if you don't memorize it; 1 is true and 0 is false, so saying if (1) is the same as saying if (1==1) because both are "truthy." This might seem convenient; it's more confusing that -1 and 42 are loosely true, or truthy. See http://php.net/manual/en/language.operators.comparison.php as well.

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.

YO MAMA HEAD posted:

Well, I realize it's because I got a little mixed up myself in trying to be didactic! You should get a general sense of http://php.net/manual/en/types.comparisons.php even if you don't memorize it; 1 is true and 0 is false, so saying if (1) is the same as saying if (1==1) because both are "truthy." This might seem convenient; it's more confusing that -1 and 42 are loosely true, or truthy. See http://php.net/manual/en/language.operators.comparison.php as well.

Ah. Thanks for trying though.

Brilliant resources, thanks for the help.

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker
Let me explain it in a different way.

Now you might be thinking that you need to put in one of these comparison operators (example: == or != or <, etc) in between the brackets of an if() to make it work. This isn't strictly true.

The stuff in between the brackets is called an expression and it works like this: if() will try to convert whatever you give it to a Boolean. It will reduce the expression to true or false and if it comes up true, php will continue on by doing whatever's in the brackets.

Here comes the fun part: almost anything is an expression and can therefore be reduced to a Boolean!

An expression as I said, can be anything. A string, number, an array, a function, object. Exactly how and when <something> is true or false, is explained by the type comparison table.

Some examples:
php:
<?

// the simplest case is to give it a boolean directly; no need to scratch your head on this one
if(true)
{
  print 'yay';
}

if(false)
{
  print 'you will never see me';
}

// numbers are easy: everything not zero is true
if(5)
{
  print 'yay';
}

if(-99.534)
{
  print 'yep, still true';
}

if(0)
{
  print 'aww.. :(';
}


/*
How about strings? well, this is a bit more complicated.
Suffice it to say that any empty string and a string with a zero in it
are false, but php tries really hard to convert the string to a number and finally 
to a boolean, but that requires way too many words and is out of the scope
of this explanation of how the if() works anyway. That comparison table
is a good starting place if you want to know more, though.
*/
if('hello i am a bit of text')
{
  print 'it works';
}

if('0')
{
  print 'sorry, bud';
}

if('2242')
{
    print 'but this works';
}

if('false')
{
    print 'this works too! Think about it...';
}

/*
arrays are false, if they are empty and that's about it
 */

$an_array = [];
if($an_array)
{
    print 'an empty array is useless, according to if()';
}

$an_array[] = 'first value in an array';

if($an_array)
{
    print 'aahhhhh that\'s nice';
}

$an_array = [false];

if($an_array)
{
  print 'this works too, because php doesn\'t care what\'s in it, just that _something_ is there';
}

?>
I think that gets the point across. Php takes the value you supply, turns it in a boolean through wizardry and magic, and trundles on.

Now, comparison operators and values aren't the only things you can put in an if(). Logical operators for example, or Arithmetic operators, or pretty much any operator. The key insight here is to understand that anything that returns a value, can be used. Like functions:

php:
<?

function test()
{
  return true;
}


$result = test();
if($result)
{
  print 'yep! Test returns true, and this value is passed to the if().';
}

// you don't need to use a variable though; this works too
if(test())
{
  print 'Woah - neo';
}

// like i said, any value can be used!
function test2()
{
  return [];
}

if(test() == false)
{
  print 'hello!';
}
if(!test())
{
  print 'i\'m the exact same statement as the previous one';
}
?>
I hope this clears things up for you.

As a suggestion I would keep real good track of what type something is in your head, whether a number, string, array, or otherwise.
There might be a lot of type juggling going on and it really pays dividends if you can immediately spot the difference between for instance '0' and 0 (when you start to work with databases you'll find that those will return everything as a string or null!). It will save you a bunch of headaches down the road because you think you're dealing with a number, but it's actually an empty array or whatever.

then you can cast a variable to a type and be sure what you're dealing with. But that's for later.

Dougie McdDouger
Nov 19, 2014

I do like muffins , but I tango all night long.
Awesome reply. Helped clear things up.

Any tips for further learning?

Adbot
ADBOT LOVES YOU

o.m. 94
Nov 23, 2009

Learning the difference between == and === is a nice supplement to truthy/falsy

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply