I've read lots about getters and setters being evil, unless there is good call for one, but I cannot figure out how to implement that knowledge into my Model layer.
Say in my Model layer I have a class that has services like:
findStudentsByID($searchCriteria)
findStudentsByLastName($searchCriteria)
...
Do I require a getter or a setter, say $searchCritera
, here so I can maintain Separation of Concerns?
Would it be wrong to simply query the model from the view with findStudentsByID(4);
? Wouldn't that bind the two too much?
I thought I could use at least a setter so I can change the state of the class and then use a method.
For example,
API enforcement:
interrace IModel{
public function setCriteria($searchCriteria);
public function findStudentByID();
public function findStudentByLastName();
}
In my model:
class Model implements IModel{
private $searchCriteria;
public function setCriteria($searchCriteria){
$this->searchCriteria = $searchCriteria;
}
public function findStudentByID(){
some SQL "WHERE student_id = " $this->searchCriteria;
return $results;
}
public function findStudentsByLastName(){
some SQL "WHERE last_name = " $this->searchCriteria;
return $results;
}
}
In my controller:
interface IController{
public function someAction($searchCriteria);
}
class Controller implements IController{
private $model;
public function __construct(IModel $model) {
$this->model = $model;
}
//for argument say this is from a front controller passing the value
public function someAction($searchCriteria){
$this->model->setCriteria($searchCriteria); //model state is changed
}
}
In my view:
interface IView{
public function students();
}
class View implements IView{
private $model;
public function __construct(IModel $model){
$this->model = $model;
}
public function students(){
return $this->model->findStudentsByLastName();
require_once("some_template_somewhere"); //get my template
}
}
some template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Form Example</title>
</head>
<body>
<h1>Students</h1>
<p>
<?php foreach($this->view->students() as $student) { ?>
<?PHP echo $student["student_id"] ?> </br>
<?PHP echo $student["LAST"] ?>
<?PHP } ?>
</p>
</body>
Implementation:
//some starting point:
$model = new Model();
$controller = new Controller($model);
$view = new View($model);
$controller->someAction($_GET['myAction']); //changing model state;
$this->view->students();
Do I really need the view there? Would it be better to simply use this in a view/template (yes, I know they're different)?
<?php foreach($this->view->model->findByStudentID(4) as $student) { ?>
<?PHP echo $student["student_id"] ?> </br>
<?PHP echo $student["LAST"] ?>
<?PHP } ?>
The only thing I can see that will help with future maintainability, which is why I want my separation of concerns to begin with, is that I can switch the layers/concerns without breaking the other layers/concerns. The interface will make sure I have the setCriteria
, etc.
From what I can see
- I could switch out the model.
- I could switch out the template.
- I could switch out the controller.
But say someone makes their own Model. If they create an additional function, won't that break everything, rippling up? What if they implement only the stock functions in my model, but they return different information? I didn't really want a separate layer in my model layer, I thought I had abstracted myself to death already, though I feel like I might be slightly better off with abstract classes instead of interfaces.
EDIT: I changed the method being called to finding the students by last name so the example makes more sense.
IModel
should be namedStudentMapperInterface
\$\endgroup\$