Would you agree this is the definition of a PHP framework?

If it’s bogus you’d be able to refute it.

Your entire argument still rests on the premise that "i don’t understand the difference therefore they are the same. It’s an appeal to ignorance, nothing else.

It doesn’t matter if concern and responsibility mean the same thing. It doesn’t follow that “Separation of responsibilities” means the same thing a “Single responsibility”.

Your entire argument is:

“Wild goose chase”

and

“golden goose”

and

“What’s good for the goose is good for the gander”

and

“goose bumps”

“Because they all use the word goose, they all refer to the same concept”

You need to explain how “Single responsibility” means the same thing as “Separate responsibilities”

You have stated they are different:

You are saying “SRP includes something SoC does not”. How does that make them “exactly the same concept”?

This can be shown in PHP as:

$SoC = 1;
$coupling = 2;
$cohesion = 4;

$SRP = $SoC + $coupling + $cohesion;

var_dump($SRP === $SoC);

Unless you can make that evaluate to true without making any of the values zero or negative (ie, meaningless or not actually included) or changing the definition of SRP so it doesn’t include all 3 concepts, or changing the operator to something other than equality (You are saying they are EXACTLY THE SAME), then your point is null and void.

if your definition of SRP is correct then you’ll be able to do the above. Otherwise your definition of SRP is wrong and your argument is lost.

That’s 8 times you’ve been unable to answer this post, 8 times you’ve proven yourself wrong.

I’m going to keep posting this until you show how the above code evaluates to true and that “wild goose chase” means the same as “goose bumps” because they both contain the word “goose”. You’re not offering any new arguments, so I’m not dignifying you with a new response.

Sorry, but if a scientist sees that a rule is being broken at the core of its definition, he simply no longer looks further.

Scott

If anyone’s interested I’ve consolidated my thoughts from this thread into a blog post here: SoCcam’s Razor: Applying the Single Responsibility Principle using a practical approach

Great article. With SoCcam’s Razor on Tony’s monster class, we’d end up with a ton of shavings. LOL! :smile:

Scott

Interesting article - at least something good has come out of this discussion :smile:

I’m wondering if entity objects follow the SRP - by entity I mean an object representing data and some helper methods for setting and getting the data. For example:

class Product {
    public $id;
    public $name;
    public $description;
    public $addedTime; /* string format: YYYY-MM-DD hh:mm:ss */
    
    public function getAddedTimeFormatted($format) {
        $time = strtotime($this->addedTime);
        return date($format, $time);
    }
    
    public function getDescriptionAsPlainText() {
        return strip_tags($this->description);
    }
    
    public function setAddedTimeFromTimestamp($timestamp) {
        $this->addedTime = date('Y-m-d H:i:s', $timestamp);
    }
}

Could we say the object’s single responsibility is holding the data in general? Or does it have multiple responsibilities because apart from holding data it can manipulate it (format) as well? It is holding 4 data properties - does this mean it has 4 separate reasons to change?

If we’re describing the class as “Holding data about the product” then Id argue anything that is formatting the data getAddedTimeFormatted and getDescriptionAsPlainText is a different responsibility; Formatting the data.

The setter may not be, but in this instance I’d argue that if you have a setter then the variable it’s setting should not be public to avoid the possibility of setting it to an invalid value (that would then cause getAddedTimeFormatted to break.)

This could easily be split into separate classes: DateFormatter and TextFormatter. This way: Date formatting and text formatting logic is reusable for other entities. I’d even go as far as calling this display logic.

edit: To be even clearer, imagine if we used a DateTime class to store the date:

class Product {
    public $id;
    public $name;
    public $description;
    public $addedTime; /* \DateTime object */

  
    public function setAddedTime(\DateTime $dateTime) {
        $this->addedTime = $dateTime;
    }
}

The formatting logic has been passed off to the DateTime class. We now call $entity->addedTime->format(); instead of $entity->getAddedTimeFormatted();

All formatting/processing of dates has now been removed from the class.

Similarly, if some external place needs the description, it’s up to that how to format the description for its own use.

edit 2. Helper functions like this are a bit of a minefield. Consider this:

class Product {
    public $id;
    public $name;
    public $description;
    public $addedTime; /* \DateTime object */
    public $price;
  
    public function setAddedTime(\DateTime $dateTime) {
        $this->addedTime = $dateTime;
    }

    public function getPrice($quanity) {
    	//If you order more than 10, you get a 20% discount
    	if ($quantity > 10) {
    		return $this->price * 0.8;
    	}
    	else {
    		return $this->price;
    	}
    }
}

This looks more reasonable doesn’t it? The problem with this is that it adds extra reasons to change to the class. Consider the following modifications to the price calculation:

  • Anyone who has spent more than £500 in the last year gets a 10% discount
  • There is a sale during august when all prices are slashed by 25%
  • Users outside the country have to pay an additional 10% tax

The problem is, these are cross-cutting concerns. Where it becomes particularly messy is when you get “All shoes are have a £20 discount”. If this is in its own class, rather than the product class, it becomes a lot more manageable.

I want to expand on this a little. Consider the following set of classes:


class BasketItem {
	public $product;
	public $quantity;
}


class PriceCalculator {
	private $modifiers = [];

	public function addModifier(PriceModier $priceModifier) {
		$this->modifiers[] = $priceModifier;
	}

	public function getPrice(BasketItem $item) {
		$price = $item->product->price;

		foreach ($this->modifiers as $modifier) {
			$price += $modifier->getDifference($item);
		}

              return $price;
	}
}


interface PriceModifier {
	public function getDifference(BasketItem $product);
}



class QuantityDiscount implements PriceModifier {

	public function getDifference(BasketItem $item) {
		if ($item->quantity > 10) {
			return 0 - ($item->product->price * 0.2);
		}
		else return 0;
	}
}


class LoyaltyDiscount implements PriceModifier {
	private $user;

	public function __construct(User $user) {
		$this->user = $user;
	}

	public function getDifference(BasketItem $item) {
		//Find the total of the users orders in the last year
	}
}

class SaleDiscount implements PriceModifier {
	public function getDifference(BasketItem $item) {
		if ($item->product->category == 'SHOES') {
			return -20;
		}
		else return 0;
	}
}

class ForeignTax implements PriceModifier {
	private $user;

	public function __construct(User $user) {
		$this->user = $user;
	}

	public function getDifference(BasketItem $item) {

		if ($this->user->countryId != 1) {
			return $item->product->price * 0.1;
		}
		else return 0;
	}
}

This better follows SOLID. The PriceCalculator class follows the open/closed principle in that it’s extensible using any of the modifiers and each modifier (and the product class itself) has a single responsibility.

The rule is that a class should contain methods and properties that form a cohesive unit, that all the parts together form a meaningful unit. You cannot tell that simply by counting the number of methods, properties and lines of code. You need to measure how much interaction there is between the various modules. That type of measurement goes far beyond a simple count.

Is there any one else here who thinks that is an intelligent question?

It isn’t the question that is intelligent, but rather the meaning behind the question.

Scott

How did we get from a single responsibility and single reason for change to that? That is obviously your own personal view of SRP, which can be right, if you follow the single reason for change and single responsibility parts too. Without them, you only have half the principle.

Scott

Let’s be clear, your arugment here is:

and

It doesn’t matter in the slightest if “responsibility” and “concern” are interchangeable. It doesn’t follow that “Single Responsibility Principle” means the same thing as “Separation of Responsibilities” because they both use the word “responsibility” any more than “Wild Goose Chase” and “Goose Bumps” mean the same thing because they both use the word “goose”.

Please clarify your argument, because all you’ve said so far is this:

  • Responsibility and Concern mean the same thing
  • Therefore “Single Responsibility principle” and “Separation of concerns” mean the same thing because they both relate to responsibilities

It makes no sense because “Wild goose chase” and “Goose bumps” both relate to geese, it doesn’t follow that they both mean the same thing.

Not to mention that by your own definition they are different.

You are not comparing like with like. If you were to talk about “separation of geese” and “single goose principle” then your argument would have merit. “Single Thing” means the same thing as “Separation of Things” because you are separating a group of “things” (plural) into single instances of “thing” (singular).

Fine, let’ use Single Goose principle and Separation of Geese, it make no difference to the argument. Single Goose Principle describes a singular goose. Separation of Geese describes how different geese are related: I’ll separate my 30 geese into 3 flocks. 10 can go to the field, 10 can go to the lake and I’ll sell the remaining 10. They’re not the same concept.

edit: This is a bit too abstract now anyway because it makes the exact same error you were making earlier: The names are just labels for concepts, the words chosen to describe the concept makes no difference.

I disagree. The idea of “separation of concerns” is to take a group of unrelated concerns and put them into separate classes. If they were already related then you would already have a cohesive unit which should not be separated any further.

Nowhere does SoC mention that 1 concern = 1 class.

edited for clarificaton

If you are trying to compare “geese” with “concerns/responsibilities” then you must keep separating them until you only have units containing a single “goose”. You separate the group into single units.

The Wikipedia article at https://en.wikipedia.org/wiki/Separation_of_concerns specifically states the following in the opening paragraph:

No, I might have a Female Geese and male geese, if my concern is breeding I’ll want to keep them together, if my concern is egg laying I’ll want to separate the males from the females so that the eggs aren’t fertilised.

General OR specific. We have said this multiple times: A small concern can be handled by a class or a module/unit/component/whatever you want to call it that is a collection of classes.

This is not my personal view it is a view put forward by Robert C. Martin in his article http://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html where he says te following