Suppose I've the following classes in my project:
class Is // validation class
class Math // number manipulation class
Now, if I want to validate a given number for primality where would be the logical place to insert my Prime() method? I can think of the following options:
Is_Math::Prime()
Math_Is::Prime()
I hate these ambiguities, the slow down my thinking process and often induce me in errors. Some more examples:
Is::Image() or Image::Is() ?
Is_Image::PNG() or Image_Is::PNG() ?
Is_i18n_US::ZipCode() or i18n_Is_US::ZipCode() or
i18n_US_Is::ZipCode() ?
In the Image example the first choice makes more sense to me while in the i18n example I prefer the last one. Not having a standard makes me feel like the whole code base is messy.
Is there a holy grail solution for organizing classes? Maybe a different paradigm?
For the Math example, I'd put the actual functionality of checking if a number is prime in the Math class. In your Is class you would put a method that would be called when a validation needs to occur. You would then use Math::Prime() from there.
With Image, that's a type check. You probably don't need to make a method for it unless you are making sure valid image data has been uploaded.
With the PNG method, same with Math. Put the actual PNG data checker algorithm in Image and make your validator method in Is call it.
The zip code example should be in your Is class only since it operates on a string primitive and probably will just use a regexp (read: it won't be a complex method, unlike your PNG checker which probably will be).
If you want to respect the SRP (http://en.wikipedia.org/wiki/Single_responsibility_principle), do the little exercice:
Select your class and try to describe what it does/can do. If you have an "AND" in your description, you must move the method to an other class.
See page 36: http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
Other Law (there are many more) that will help you organize your classes: Law of Demeter (http://en.wikipedia.org/wiki/Law_of_Demeter).
To learn a lot and to help you make the right choice, I advice you Misko's blog (A google evangelist): http://misko.hevery.com
Hope this helps.
I don't think it's ambiguous at all. "Is" should be first in every one of those examples, and I'll tell you why: "Is" is the superset of validation operations in which Is::Math is a member.
In the case of Is::Math, what are you doing? Are you doing math operations? Or are you validating mathematical entities? The latter, obviously, otherwise it'd just be "Math".
Which of those two operations has the greater scope? Is? Or Math? Is, obviously, because Is is conceptually applicable to many non-Math entities, whereas Math is Math specific. (Likewise in the case of Math::Factor, it wouldn't be Factor::Math, because Math is the superset in which Factor belongs.)
The whole purpose of this type of OOPing is to group things in a manner that makes sense. Validation functions, even when they apply to wildly different types of entities (Prime numbers vs. PNG images) have more similarities to each other than they do to the things they are comparing. They will return the same types of data, they are called in the same kind of situations.
Everything about handling validation in itself would fit in your Is-classes:
Did it pass?
Which parts did not pass?
Should the validation errors be logged somewhere?
Zend_Validate in Zend Framework provides such an approach, maybe you can get some inspiration from it. Since this approach would have you implementing the same interface in all validation-classes, you could easily
use the same syntax for validation, independantly of which data is validated
easily recognize which validation rules you have available by checking for all classes named Is_Prime, Is_Image instead of checking for Math_Is, Image_Is all over the place.
Edit:
Why not use a syntax like this:
class Math {
public function isPrime() {
$validation_rule = new Is_Prime();
return (bool) $validation_rule->validates($this->getValue());
}
}
And thereby also allow
class Problem {
public function solveProblem(Math $math) {
$validation_rule = new Is_Prime();
if($validation_rule->validates($math->getValue())) {
return $this->handlePrime($math);
} else {
return $this->handleNonPrime($math);
}
}
}
I think there is no "The Right Answer" to the problem you stated. Some people will put Prime in Is, and some in Math. There is ambiguity. Otherwise you wouldn't be asking this question.
Now, you have to resolve the ambiguity somehow. You can think about some rules and conventions, that would say which class/method goes where. But this may be fragile, as the rules are not always obvious, and they may become very complicated, and at that point they're no longer helpful.
I'd suggest that you design the classes so that it's obvious by looking at the names where some method should go.
Don't name your validation package Is. It's so general name that almost everything goes there. IsFile, IsImage, IsLocked, IsAvailable, IsFull - doesn't sound good, ok? There is no cohesion with that design.
It's probably better to make the validation component filter data at subsystems boundary (where you have to enforce security and business rules), nothing else.
After making that decision, your example becomes obvious. Prime belongs in Math. Is::Image is probably too general. I'd prefer Image::IsValid, because you'll probably also have other methods operating on an image (more cohesion). Otherwise "Is" becomes a bag for everything, as I said at the beginning.
I don't think "is" belongs in class names at all. I think that's for methods.
abstract class Validator {}
class Math_Validator extends Validator
{
public static function isPrime( $number )
{
// whatever
}
}
class I18N_US_Validator extends Validator
{
public static function isZipCode( $input )
{
// whatever
}
}
class Image_Validator extends Validator
{
public static function isPng( $path )
{
// whatever
}
}
Math_Validator::isPrime( 1 );
I18N_US_Validator::isZipCode( '90210' );
Image_Validator::isPng( '/path/to/image.png' );
Is there a holy grail solution for organizing classes? Maybe a different paradigm?
No, that is a basic flaw of class based oop. It's subjective.
Functional programming (Not to be confused with procedural programming) has less problems with this matter, mostly because the primary building blocks are much smaller. Classless oop also deals better, being a hybrid of oop and functional programming of sorts.
Classes can be considered to be fancy types that do things, like validating themselves.
abstract class ValidatingType
{
protected $val;
public function __construct($val)
{
if(!self::isValid($val))
{ // complain, perhaps by throwing exception
throw new Exception("No, you can't do that!");
}
$this->val = $val;
}
abstract static protected function isValid($val);
}
We extend ValidatingType to create a validating type. That obliges us to create an isValid method.
class ValidatingNumber extends ValidatingType
{
...
static protected function isValid($val)
{
return is_numeric($val);
}
}
class ValidatingPrimeNumber extends ValidatingNumber
{
/*
* If your PHP doesn't have late-binding statics, then don't make the abstract
* or overridden methods isValid() static.
*/
static protected function isValid($val)
{
return parent::isValid($val)
or self::isPrime($val); // defined separately
}
}
class ValidatingImage extends ValidatingType
{
...
static protected function isValid($val)
{
// figure it out, return boolean
}
}
One advantage of this approach is that you can continue to create new validating types, and you don't get a ballooning Is class.
There are more elegant variations on this approach. This is a simple variation. The syntax may require cleaning up.
Related
I have classes MonthTimeCard and MonthReport. They use same input field for choosing month, so the validation is the same and initialisation is the same.
class MonthTimeCard {
private function setPrivateVarsByUserInput()
{
$this->month_from_input = '2015-09';
$this->date_from = '2015-09-01';
$this->date_to = '2015-09-30';
// lets say those 3 values are formated, validated and returned as array from MonthUserInput class.
// but I have to repeat code in my both classes to initialize them
// I could have one liner like $this->data = $this->monthUserInput->getInput();
// but current class code will need to call $this->data->[variable] everywhere - not looking very nice,
// because ->data is not usefull here, just extra characters.
}
}
Class MonthReport {
... same initialisation
}
I now just hard coded them but you know assignment will be from return array of MonthUserInput class which will validate. There is only one user input field which gets string like '2015-09' and MonthUserInput class will add first day and last day of month.
I could avoid this if I would use inheritance but I have read that should avoid and some even say that it should be removed from OOP.
http://blogs.perl.org/users/sid_burn/2014/03/inheritance-is-bad-code-reuse-part-1.html
With inheritance I would simply in do validating and setting user input in parent class and so no duplication.
How should I do this now? Of course its just 3 variables in this example, I plan to have 5, its not much, but still its duplication and with inheritance there would not be duplication in this case.
Update
I would like to see explanation which I could use to explain to anybody who do not agree that inheritance would be bad to this situation. For example I discussed with one experienced programmer and he does not see a problem here to use inheritance for code reuse. I just said there is lot on internet telling that use composition, but that was not good argument for this situation.
For example:
Favor composition over inheritance. If two classes don't have an "is
a" relationship, then it should never be necessary to use inheritance
to achieve code reuse. Never.
this would not be a good argument for some people. They can ask - who invented those rules and why? They do not see a problem by breaking this rule.
Inheritance is a powerful tool and can achieve code reuse, however it brings potential problems of its own and should be used appropriately. Because subclasses depend on the superclass implementation, inheritance breaks encapsulation and can make code more fragile and difficult to maintain.
Achieve the discipline to use inheritance only when there really is a "IS A" relationship, eg. a PreferredClient IS A Client ... or ... a MountainBike IS A Bike. If you are designing a class that doesn't achieve an IS A relationship with an intended superclass, then don't use inheritance.
You can achieve a similar degree of code reuse by using composition instead of inheritance. Instead of making a subclass, incorporate the intended superclass as an attribute of your class. This allows you to delegate method calls to the contained instance and achieve code reuse.
For your code example, a suggested code decomposition might be this:
class MonthTimeCard {
Month myMonth;
MonthTimeCard(Month month) { myMonth = month; }
private function setPrivateVarsByUserInput() {
// calls to myMonth
}
}
Class MonthReport {
// calls to myMonth
}
Class Month {
$this->month_from_input = ...
$this->date_from = ...
$this->date_to = ...
}
If MonthTimeCard and MonthReport do not logically extend each other (such as Dog and Cat are sub types of Animal), its not a good idea to use inheritance here anyway.
Besides that, if you do the same validation at multiple locations, you could introduce a standalone DateValidator class and use that whenever required.
public class DateValidator {
public static boolean validate(final String dateString) {
return ...; // TODO: Validate user input here
}
}
tl;dr
What strategies exist to overcome parameter type invariance for specializations, in a language (PHP) without support for generics?
Note: I wish I could say my understanding of type theory/safety/variance/etc., was more complete; I'm no CS major.
Situation
You've got an abstract class, Consumer, that you'd like to extend. Consumer declares an abstract method consume(Argument $argument) which needs a definition. Shouldn't be a problem.
Problem
Your specialized Consumer, called SpecializedConsumer has no logical business working with every type of Argument. Instead, it should accept a SpecializedArgument (and subclasses thereof). Our method signature changes to consume(SpecializedArgument $argument).
abstract class Argument { }
class SpecializedArgument extends Argument { }
abstract class Consumer {
abstract public function consume(Argument $argument);
}
class SpecializedConsumer extends Consumer {
public function consume(SpecializedArgument $argument) {
// i dun goofed.
}
}
We're breaking Liskov substitution principle, and causing type safety problems. Poop.
Question
Ok, so this isn't going to work. However, given this situation, what patterns or strategies exist to overcome the type safety problem, and the violation of LSP, yet still maintain the type relationship of SpecializedConsumer to Consumer?
I suppose it's perfectly acceptable that an answer can be distilled down to "ya dun goofed, back to the drawing board".
Considerations, Details, & Errata
Alright, an immediate solution presents itself as "don't define the consume() method in Consumer". Ok, that makes sense, because method declaration is only as good as the signature. Semantically though the absence of consume(), even with a unknown parameter list, hurts my brain a bit. Perhaps there is a better way.
From what I'm reading, few languages support parameter type covariance; PHP is one of them, and is the implementation language here. Further complicating things, I've seen creative "solutions" involving generics; another feature not supported in PHP.
From Wiki's Variance (computer science) - Need for covariant argument types?:
This creates problems in some situations, where argument types should be covariant to model real-life requirements. Suppose you have a class representing a person. A person can see the doctor, so this class might have a method virtual void Person::see(Doctor d). Now suppose you want to make a subclass of the Person class, Child. That is, a Child is a Person. One might then like to make a subclass of Doctor, Pediatrician. If children only visit pediatricians, we would like to enforce that in the type system. However, a naive implementation fails: because a Child is a Person, Child::see(d) must take any Doctor, not just a Pediatrician.
The article goes on to say:
In this case, the visitor pattern could be used to enforce this relationship. Another way to solve the problems, in C++, is using generic programming.
Again, generics can be used creatively to solve the problem. I'm exploring the visitor pattern, as I have a half-baked implementation of it anyway, however most implementations as described in articles leverage method overloading, yet another unsupported feature in PHP.
<too-much-information>
Implementation
Due to recent discussion, I'll expand on the specific implementation details I've neglected to include (as in, I'll probably include way too much).
For brevity, I've excluded method bodies for those which are (should be) abundantly clear in their purpose. I've tried to keep this brief, but I tend to get wordy. I didn't want to dump a wall of code, so explanations follow/precede code blocks. If you have edit privileges, and want to clean this up, please do. Also, code blocks aren't copy-pasta from a project. If something doesn't make sense, it might not; yell at me for clarification.
With respect to the original question, hereafter the Rule class is the Consumer and the Adapter class is the Argument.
The tree-related classes are comprised as follows:
abstract class Rule {
abstract public function evaluate(Adapter $adapter);
abstract public function getAdapter(Wrapper $wrapper);
}
abstract class Node {
protected $rules = [];
protected $command;
public function __construct(array $rules, $command) {
$this->addEachRule($rules);
}
public function addRule(Rule $rule) { }
public function addEachRule(array $rules) { }
public function setCommand(Command $command) { }
public function evaluateEachRule(Wrapper $wrapper) {
// see below
}
abstract public function evaluate(Wrapper $wrapper);
}
class InnerNode extends Node {
protected $nodes = [];
public function __construct(array $rules, $command, array $nodes) {
parent::__construct($rules, $command);
$this->addEachNode($nodes);
}
public function addNode(Node $node) { }
public function addEachNode(array $nodes) { }
public function evaluateEachNode(Wrapper $wrapper) {
// see below
}
public function evaluate(Wrapper $wrapper) {
// see below
}
}
class OuterNode extends Node {
public function evaluate(Wrapper $wrapper) {
// see below
}
}
So each InnerNode contains Rule and Node objects, and each OuterNode only Rule objects. Node::evaluate() evaluates each Rule (Node::evaluateEachRule()) to a boolean true. If each Rule passes, the Node has passed and it's Command is added to the Wrapper, and will descend to children for evaluation (OuterNode::evaluateEachNode()), or simply return true, for InnerNode and OuterNode objects respectively.
As for Wrapper; the Wrapper object proxies a Request object, and has a collection of Adapter objects.
The Request object is a representation of the HTTP request.
The Adapter object is a specialized interface (and maintains specific state) for specific use with specific Rule objects. (this is where the LSP problems come in)
The Command object is an action (a neatly packaged callback, really) which is added to the Wrapper object, once all is said and done, the array of Command objects will be fired in sequence, passing the Request (among other things) in.
class Request {
// all teh codez for HTTP stuffs
}
class Wrapper {
protected $request;
protected $commands = [];
protected $adapters = [];
public function __construct(Request $request) {
$this->request = $request;
}
public function addCommand(Command $command) { }
public function getEachCommand() { }
public function adapt(Rule $rule) {
$type = get_class($rule);
return isset($this->adapters[$type])
? $this->adapters[$type]
: $this->adapters[$type] = $rule->getAdapter($this);
}
public function commit(){
foreach($this->adapters as $adapter) {
$adapter->commit($this->request);
}
}
}
abstract class Adapter {
protected $wrapper;
public function __construct(Wrapper $wrapper) {
$this->wrapper = $wrapper;
}
abstract public function commit(Request $request);
}
So a given user-land Rule accepts the expected user-land Adapter. If the Adapter needs information about the request, it's routed through Wrapper, in order to preserve the integrity of the original Request.
As the Wrapper aggregates Adapter objects, it will pass existing instances to subsequent Rule objects, so that the state of an Adapter is preserved from one Rule to the next. Once an entire tree has passed, Wrapper::commit() is called, and each of the aggregated Adapter objects will apply it's state as necessary against the original Request.
We are then left with an array of Command objects, and a modified Request.
What the hell is the point?
Well, I didn't want to recreate the prototypical "routing table" common in many PHP frameworks/applications, so instead I went with a "routing tree". By allowing arbitrary rules, you can quickly create and append an AuthRule (for example) to a Node, and no longer is that whole branch accessible without passing the AuthRule. In theory (in my head) it's like a magical unicorn, preventing code duplication, and enforcing zone/module organization. In practice, I'm confused and scared.
Why I left this wall of nonsense?
Well, this is the implementation for which I need to fix the LSP problem. Each Rule corresponds to an Adapter, and that ain't good. I want to preserve the relationship between each Rule, as to ensure type safety when constructing the tree, etc., however I can't declare the key method (evaluate()) in the abstract Rule, as the signature changes for subtypes.
On another note, I'm working on sorting out the Adapter creation/management scheme; whether it is the responsibility of the Rule to create it, etc.
</too-much-information>
To properly answer this question, we must really take a step back and look at the problem you're trying to solve in a more general manner (and your question was already pretty general).
The Real Problem
The real problem is that you're trying to use inheritance to solve a problem of business logic. That's never going to work because of LSP violations and -more importantly- tight coupling your business logic to the application's structure.
So inheritance is out as a method to solve this problem (for the above, and the reasons you stated in the question). Fortunately, there are a number of compositional patterns that we can use.
Now, considering how generic your question is, it's going to be very hard to identify a solid solution to your problem. So let's go over a few patterns and see how they can solve this problem.
Strategy
The Strategy Pattern is the first that came to my mind when I first read the question. Basically, it separates the implementation details from the execution details. It allows for a number of different "strategies" to exist, and the caller would determine which to load for the particular problem.
The downside here is that the caller must know about the strategies in order to pick the correct one. But it also allows for a cleaner distinction between the different strategies, so it's a decent choice...
Command
The Command Pattern would also decouple the implementation just like Strategy would. The main difference is that in Strategy, the caller is the one that chooses the consumer. In Command, it's someone else (a factory or dispatcher perhaps)...
Each "Specialized Consumer" would implement only the logic for a specific type of problem. Then someone else would make the appropriate choice.
Chain Of Responsibility
The next pattern that may be applicable is the Chain of Responsibility Pattern. This is similar to the strategy pattern discussed above, except that instead of the consumer deciding which is called, each one of the strategies is called in sequence until one handles the request. So, in your example, you would take the more generic argument, but check if it's the specific one. If it is, handle the request. Otherwise, let the next one give it a try...
Bridge
A Bridge Pattern may be appropriate here as well. This is in some sense similar to the Strategy pattern, but it's different in that a bridge implementation would pick the strategy at construction time, instead of at run time. So then you would build a different "consumer" for each implementation, with the details composed inside as dependencies.
Visitor Pattern
You mentioned the Visitor Pattern in your question, so I'd figure I'd mention it here. I'm not really sure it's appropriate in this context, because a visitor is really similar to a strategy pattern that's designed to traverse a structure. If you don't have a data structure to traverse, then the visitor pattern will be distilled to look fairly similar to a strategy pattern. I say fairly, because the direction of control is different, but the end relationship is pretty much the same.
Other Patterns
In the end, it really depends on the concrete problem that you're trying to solve. If you're trying to handle HTTP requests, where each "Consumer" handles a different request type (XML vs HTML vs JSON etc), the best choice will likely be very different than if you're trying to handle finding the geometric area of a polygon. Sure, you could use the same pattern for both, but they are not really the same problem.
With that said, the problem could also be solved with a Mediator Pattern (in the case where multiple "Consumers" need a chance to process data), a State Pattern (in the case where the "Consumer" will depend on past consumed data) or even an Adapter Pattern (in the case where you're abstracting a different sub-system in the specialized consumer)...
In short, it's a difficult problem to answer, because there are so many solutions that it's hard to say which is correct...
The only one known to me is DIY strategy: accept simple Argument in function definition and immediately check if it is specialized enough:
class SpecializedConsumer extends Consumer {
public function consume(Argument $argument) {
if(!($argument instanceof SpecializedArgument)) {
throw new InvalidArgumentException('Argument was not specialized.');
}
// move on
}
}
I'm trying to design some class hierarchy and I got "stuck" at this part.
Lets say that I have following classes
abstract class Video
{
const TYPE_MOVIE = 1;
const TYPE_SHOW = 2;
abstract public function getTitle();
abstract public function getType();
}
class Movie extends Video
{
// ...
public function getType()
{
return self::TYPE_MOVIE;
}
}
class Show extends Video
{
// ...
public function getType()
{
return self::TYPE_SHOW;
}
}
In the diffrent part of the system I have (Parser) class that encapsulates creation of
movie and show objects and returns obj. to the client.
Question: What is the best way to get a type of a obj. returned from parser/factory class, so that client can do something like
$video = $parser->getVideo('Dumb and Dumber');
echo $video->getTitle();
// Way 1
if($video->getType == 'show') {
echo $video->getNbOfSeasons();
}
// Way 2
if($video instanceof Show) {
echo $video->getNbOfSeasons();
}
// Current way
if($video->getType == Video::TYPE_SHOW) {
echo $video->getNbOfSeasons();
}
Is there a better way than my solution (read as: does my solution suck?)?
Is there a better way than my solution (read as: does my solution suck?)?
Your solution does not suck, per se. However, whenever someone is trying to determine the subtype to perform some actions, I tend to wonder; why? This answer might be a little theoretical and perhaps even a little pedantic, but here goes.
You shouldn't care. The relationship between a parent and a child class is that the child class overwrites the behaviour of the parent. A parent class should always be substitutable by it's children, regardless which one. If you find yourself asking: how do I determine the subtype, you're usually doing one of two things "wrong":
You're attempting to perform an action based upon subtype. Normally, one would opt for moving that action to the class itself, instead of "outside" of the class. This makes for more manageable code as well.
You're attempting to fix a problem you've introduced yourself by using inheritance, where inheritance isn't warranted. If there is a parent, and there are children, each of which are to be used differently, each of which have different methods, just stop using inheritance. They're not the same type. A film is not the same a tv-serie, not even close. Sure, you can see both on your television, but the resemblance stops there.
If you're running into issue number 2, you're probably using inheritance not because it makes sense, but simply to reduce code duplication. That, in and on itself, is a good thing, but the way you're attempting to do so might not be optimal. If you can, you could use composition instead, although I have my doubts where the duplicated behaviour would be, apart from some arbitrary getters and setters.
That said, if your code works, and you're happy with it: go for it. This answer is correct in how to approach OO, but I don't know anything about the rest of your application, so the answer is generic.
I'd go with way 2. It abstracts you the need to add another constant at Video in case you may want to add class SoapOpera extends Show (for instance).
With way #2, you are less dependent on constants. Whatever information you can gain without hardcoding it, means less problems to likely happen in the future in case you want to extend. Read about Tight an Loose Coupling.
I think the second option is better, using instanceof. This is in general common to all OOP design and not just PHP.
With your first option, you have specifics about derived classes in the base class, and thus must modify the base class for each new derived class you add, which should always be avoided.
Leaving the base class as-is when adding new derived classes promotes code reuse.
If there is a "right" way, and everything is subjective in coding of course (as long as it doesn't adversely impact performance/maintainability ;) ), then it's the second way as "Truth" and "Brady" have pointed out.
The upside of doing things the way you're doing them now (class constants in the abstract) is that when you're working with other developers it can provide hints as to how you expect the abstract class to be interacted with.
For instance:
$oKillerSharkFilm = Video::factory(Video::MOVIE, 'Jaws', 'Dundundundundundun');
$oKillerSharkDocumentary = Video::factory(Video::DOCUMENTARY, 'Jaws', 'A Discovery Shark Week Special');
Of course, the downside is that you have to maintain the "allowable extensions" in the abstract class.
You could still use the instanceof method as demonstrated in your question and maintain the list of allowable extension in the abstract predominantly for control/type fixing.
(Note: this is related to this question, but I think it could have been written more clearly, so I'm trying again -- my update only helped to a limited extent.)
I've inherited some code that creates a complex form with numerous sections, and lots of possible views, depending on a number of parameters. I've been working with it for a while, and finally have a chance to think about doing some re-factoring. It's currently written procedurally, with a bunch of functions that look like this:
get_section_A ($type='foo', $mode='bar', $read_only=false, $values=array()) {
if ($this->type == 'foo') {
if ($this->mode == 'bar') { }
else { }
} else { }
}
Passing around those parameters is nasty, so I've started writing a class like this:
class MyForm {
public $type; // or maybe they'd be private or
public $mode; // I'd use getters and setters
public $read_only; // let's not get distracted by that :)
public $values;
// etc.
function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
$this->type = $type;
// etc.
}
function get_sections () {
$result = $this->get_section_A();
$result .= $this->get_section_B();
$result .= $this->get_section_C();
}
function get_section_A() {
if ($this->type == 'foo') { }
else { }
}
function get_section_B() {}
function get_section_C() {}
// etc.
}
The problem is that the procedural functions are split into a few files (for groups of sections), and if I combine them all into a single class file, I'm looking at 2500 lines, which feels unwieldy. I've thought of a few solutions:
keep living with the nasty parameters and do something else with my time :)
live with having a 2500 line file
create a separate class for each group of sections that somehow "knows" the values of those parameters
If I do #3, I've thought of two basic approaches:
pass the MyForm object in as a single parameter
create a FormSectionGroup class with static properties that get set in MyForm, then in the group files, each class would extend FormSectionGroup and automatically have access to the current values for those parameters.
1) is probably easier to set-up, and once I'm inside get_section_A() whether I say $this->type or $myForm->type isn't all that different, but it's not exactly OOP. (In fact, I could do that without really changing to an OOP approach.)
Are there other approaches? Thoughts about which is better?
I would love nothing more than to write a lengthy explanation of how to do this, but I'm feeling a bit lazy. I do however have enough energy to point you instead to Zend_Form from the zend framework. There may be some dependencies to make it work properly (Zend_View, Elements, Decorators), but once you have them, it handles that type of situations quite gracefully.
I thought of this when I posted in your previous question - this problem reeks of decorator pattern.
It's going to be no small task, though. But I think you'll have an amazing sense of satisfaction/accomplishment once you get it done.
Having done a lot of Cocoa programming recently, I tend to view things in MVC-pattern (Model-View-Controller) terms. Hence, I'd look at the form as a controller of its various sections.
Each section object should be responsible for keeping track of its status, values and whether or not it should be displayed. Or to be precise, the section_model would take care of the values (default values, validation, etc), the section_view would take care of displaying (or not) parts of the section and the section_controller would send keep track of the status of the section and report results to the form object.
The form object should instantiate the section controllers, tell them to display or hide or whatever, and get status reports. The form object, really act a controller, can then decide when the form if completely filled out. You may have a form_model object to save the collected data, or maybe you'd rather have the section_model objects take part of that. It will take a while to get a feeling for how the different objects interact but I know from experience that if you are disciplined in designing your objects (the key is: what is an object's responsibility and what is not), you will gain a better overview and your code will be easier to upgrade. Once you find that improvements start to arise naturally, you are on the right track.
If you have the time to work on doing #3, you will probably be the happiest over the long run. Personally, I don't have the time in my job to refactor to that degree very often, and so I'd probably be forced to pick #1. #2 sounds like the worst of both worlds to me. Lots of work to get code you don't like.
I'm kind of new in PHP. For some reason in other types of programming languages like JAVA I have no problem with using setters and getters for every single variable, but when I'm programming in PHP probably because it is so flexible it feels kind of like a waste of time. It feels simpler to just set the class attributes as public most of the time and manipulating them like that. The thing is that when I do it like this I feel like I'm doing something wrong and going against OO principles.
Is it really that wrong not using setters and getters? Why or why not? How do you guys do it most of the time?
The main problem with not using property accessors is that if you find out you ever need to change a field to a property later on – to make it a computed property in a subclass, for instance – you’ll break clients of your API. For a published library, this would be unacceptable; for an internal one, just quite a lot of work fixing things.
For private code or small apps, it could be feasible to just wing it. An IDE (or text editor) will let you generate accessor boilerplate and hide it using code folding. This arguably makes using getters and setters mechanically fairly easy.
Note that some programming languages have features to synthesise the default field+getter+setter – Ruby does it via metaprogramming, C# has auto-implemented properties. And Python sidesteps the issue completely by letting you override attribute access, letting you encapsulate the attribute in the subclass that needs it instead of having to bother with it up front. (This is the approach I like best.)
The point of getters or setters is that you can still add logic to your modifications of the field in one place instead of everyplace you want to modify or retrieve the field. You also gain control at class level what happens with the field.
If we're talking strictly about PHP here and not about C#, Java, etc (where the compiler will optimise these things), I find getters and setters to be a waste of resources where you simply need to proxy the value of a private field and do nothing else.
On my setup, I made two crappy classes, one with five private fields encapsulated by five getter/setter pairs proxying the field (which looked almost exactly like java code, funnily enough) and another with five public fields, and called memory_get_usage() at the end after creating an instance. The script with the getter/setters used 59708 bytes of memory and the script with the public fields used 49244 bytes.
In the context of a class library of any significant size, such as a web site framework, these useless getters and setters can add up to a HUGE black hole for memory. I have been developing a framework for my employer in PHP (their choice, not mine. i wouldn't use it for this if i had the choice but having said that, PHP is not imposing any insurmountable restrictions on us) and when I refactored the class library to use public fields instead of getters/setters, the whole shebang ended up using 25% less memory per request at least.
The __get(), __set() and __call() 'magic' methods really shine for handling interface changes. When you need to migrate a field to a getter/setter (or a getter/setter to a field) they can make the process transparent to any dependent code. With an interpreted language it's a bit harder to find all usages of a field or method even with the reasonably good support for code sensitivity provided by Eclipse PDT or Netbeans, so the magic methods are useful for ensuring that the old interface still delegates to the new functionality.
Say we have an object which was developed using fields instead of getters/setters, and we want to rename a field called 'field' to 'fieldWithBetterName', because 'field' was inappropriate, or no longer described the use accurately, or was just plain wrong. And say we wanted to change a field called 'field2' to lazy load its value from the database because it isn't known initially using a getter...
class Test extends Object {
public $field;
public $field2;
}
becomes
class Test extends Object {
public $fieldWithBetterName = "LA DI DA";
private $_field2;
public function getField2() {
if ($this->_field2 == null) {
$this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName);
}
return $this->_field2;
}
public function __get($name) {
if ($name == 'field')) {
Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
return $this->fieldWithBetterName;
}
elseif ($name == 'field2') {
Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
return $this->getField2();
}
else return parent::__get($name);
}
}
$t = new Test;
echo $t->field;
echo $t->field2;
(As a side note, that 'extends Object' bit is just a base class I use for practically everything which has a __get() and a __set() declaration which throws an exception when undeclared fields are accessed)
You can go backwards with __call(). This example is quite brittle, but it's not hard to clean up:
class Test extends Object {
public $field2;
public function __call($name, $args) {
if (strpos($name, 'get')===0) {
$field = lcfirst($name); // cheating, i know. php 5.3 or greater. not hard to do without it though.
return $this->$field;
}
parent::__call($name, $args);
}
}
Getter and setter methods in PHP are good if the setter has to do something, or if the getter has to lazy load something, or ensure something has been created, or whatever, but they're unnecessary and wasteful if they do nothing other than proxy the field, especially with a few techniques like the ones above to manage interface changes.
I am probably not going to get many upvotes on this one, but personally getters and even more so setters feel like a code smell to me. Designs should be behavior driven, not data driven. Of course, this is just an opinion. If you have an object that depends on a particular data field of another object this is very tight coupling. Instead it should depend on the behavior of that object which is far less brittle than its data.
But yes, property like getters and setters are a step up from a dependency on a field directly for this very reason. It is less brittle and loosens up the coupling between the objects.
Did you consider to use magic functions __set/__get? Using them you can easily merge all getter/setter function in only 2 functions!
There is a way to emulate get/set without actually using get/set function class, so your code remains tidy:
$person->name = 'bob';
echo $person->name;
Take a look at this class I have coded.
Typically, when using this class, you would declare all your properties protected (or private). In the event where you'd want to add a behaviour on a property, say strtolower() + ucfirst() on the "name" property, all you'd need to do is declare a protected set_name() function in your class and the behavior should get picked up automatically. Same can be accomplished with get_name().
// Somewhere in your class (that extends my class).
protected function set_name($value) { $this->name = ucfirst(strtolower($value)); }
//
// Now it would store ucfirst(strtolower('bob')) automatically.
$person->name = 'bob';
P.S.
Another cool thing is you can make up non-existing fields such as
echo $person->full_name;
without having such fields (as long as there is a get_full_name() function).
If you access these variable in your script lots of time and if you update yoru class often you should use setters and getter because but if you dont this , when you improve your class you have to update all files which uses this variable .
Secondly main reason why you do this is you should not access variable directly because class structure may change and this data can be providen differently.While you are getting data from class you should not care about how this data is generated .Class have to care about this data proccessing so you only should care what will you get.