【问题标题】:How does this control architecture script look?这个控制架构脚本看起来如何?
【发布时间】:2010-09-24 14:02:45
【问题描述】:

我正在寻找有关我的控制架构脚本(如下所示)的反馈。具体来说,我正在寻找有关脚本设计、组织、评论和格式的反馈。我喜欢 php 编程作为一种爱好,并且正在寻找可以改进我的代码的地方。

提前致谢!

class FrontController extends ActionController {

//Declaring variable(s)
private static $instance;
protected $controller;

//Class construct method
public function __construct() {}

//Starts new instance of this class with a singleton pattern
public static function getInstance() {
    if(!self::$instance) {
        self::$instance = new self();
    }
    return self::$instance;
}

public function dispatch($throwExceptions = false) {

    /* Checks for the GET variables $module and $action, and, if present,
     * strips them down with a regular expression function with a white
     * list of allowed characters, removing anything that is not a letter,
     * number, underscore or hyphen.
     */
    $regex  = '/[^-_A-z0-9]+/';
    $module = isset($_GET['module']) ? preg_replace($regex, '', $_GET['module']) : 'home';
    $action = isset($_GET['action']) ? preg_replace($regex, '', $_GET['action']) : 'frontpage';

    /* Generates Actions class filename (example: HomeActions) and path to
     * that class (example: home/HomeActions.php), checks if $file is a
     * valid file, and then, if so, requires that file.
     */
    $class = ucfirst($module) . 'Actions';
    $file  = $this->pageDir . '/' . $module . '/' . $class . '.php';

    try {

        //Checks for existance of file
        if (!is_file($file)) {
            throw new Exception('File not found!');
        }

        //Includes file
        require_once $file;

        /* Creates a new instance of the Actions class (example: $controller
         * = new HomeActions();), and passes the registry variable to the
         * ActionController class.
         */
        $controller = new $class();
        $controller->setRegistry($this->registry);

        //Trys the setModule method in the ActionController class
        $controller->setModule($module);

        /* The ActionController dispatchAction method checks if the method
         * exists, then runs the displayView function in the
         * ActionController class.
         */    
        $controller->dispatchAction($action);

    } catch(Exception $error) {

        /* An exception has occurred, and will be displayed if
         * $throwExceptions is set to true.
         */
        if($throwExceptions) {
            echo $error;
        }
    }
}
}

abstract class ActionController {

//Declaring variable(s)
protected $registry;
protected $module;
protected $registryItems = array();

//Class construct method
public function __construct(){}

public function setRegistry($registry) {

    //Sets the registry object
    $this->registry = $registry;

    /* Once the registry is loaded, the controller root directory path is
     * set from the registry.  This path is needed for the controller
     * classes to work properly.
     */
    $this->setPageDir();
}

//Sets the controller root directory from the value stored in the registry
public function setPageDir() {
    $this->pageDir = $this->registry->get('pageDir');
}

//Sets the module
public function setModule($module) {
    $this->module = $module;
}

//Gets the module
public function getModule() {
    return $this->module;
}

/* Checks for actionMethod in the Actions class (example: doFrontpage()
 * within home/HomeActions.php) with the method_exists function and, if
 * present, the actionMethod and displayView functions are executed.
 */  
public function dispatchAction($action) {
    $actionMethod = 'do' . ucfirst($action);
    if (!method_exists($this, $actionMethod)) {
        throw new Exception('Action not found!');
    }
    $this->$actionMethod();
    $this->displayView($action);
}

public function displayView($action) {
    if (!is_file($this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php')) {
        throw new Exception('View not found!');
    }

    //Sets $this->actionView to the path of the action View file
    $this->actionView = $this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php';

    //Sets path of the action View file into the registry
    $this->registry->set('actionView', $this->actionView);

    //Includes template file within which the action View file is included
    require_once $this->pageDir . '/default.tpl';
}
}

class Registry {

//Declaring variables
private $store;

//Class constructor
public function __construct() {}

//Sets registry variable
public function set($label, $object) {
    $this->store[$label] = $object;
}

//Gets registry variable    
public function get($label) {
    if(isset($this->store[$label])) {
        return $this->store[$label];
    } else {
        return false;          
    }
}

//Adds outside array of registry values to $this->store array
public function addRegistryArray($registryItems) {
    foreach ($registryItems as $key => $value) {
        $this->set($key, $value);
    }
}

//Returns registry array
public function getRegistryArray() {
    return $this->store;
}
}

【问题讨论】:

    标签: php oop coding-style feedback


    【解决方案1】:

    无需详细查看您的代码:

    尝试通过使用有意义的函数和变量名称来编写不言自明的代码。仅在代码的目的或功能不明确的情况下使用 cmets。例如。

    //Declaring variable(s)
    //Class construct method
    //Checks for existance of file
    //Includes file
    

    都是无用的cmets,因为代码本身已经足够清晰了。

    值得一读的书:Clean Code

    【讨论】:

    • 我同意这个答案。你会遇到很多对 cme​​ts 抱有狂野信念的人,从“你的代码应该是 50% cmets 和 50% code”(我在学校时的一位教授)到“程序员不需要 cmets,那只是为了看不懂代码的人”(DreamInCode 上的某个人)。评论应该解释令人困惑的事情,并节省时间。你不需要解释如何编程,你不需要过于冗长,但你需要大致解释你的代码试图做什么,任何真正复杂的东西都值得解释。
    • 我已向我的图书馆索取该书。我还将尝试删除您指出的 cmets。还有其他反馈意见吗?再次感谢您的帮助!
    【解决方案2】:

    我在过于本地化的密切投票和想要评论代码之间左右为难。另外,现在代码太多了,所以我只评论几件事:

    1) 文档风格

    为什么不使用既定的文档格式,例如PHPDoc?

    2) 格式化

    据我所知是一致的,但我建议使用广泛使用的编码约定,例如 PEAR 或 ZF(基于 PEAR)而不是自己做(你的很接近无论如何,PEAR,所以你不妨完全采用它)。

    3) 单例模式

    为了让Singleton 工作,它必须有一个私有的 __contruct 和 __clone 方法。但我建议根本不要使用它。许多人认为 Singleton 是一种反模式。有很多关于 SO 的问题都在讨论单例模式的缺点,所以看看周围。如果应该只有一个实例,那么就不要实例化第二个。如果需要在其他类中访问 FrontController,inject it。

    4) 方法长度

    我可能会尝试缩短dispatch 方法。基本上,如果您描述了一个方法的作用并且您必须使用 and 来这样做,那么该部分应该进入它自己的方法。尝试将方法制作成小的离散单元。这也将使UnitTesting 更容易。

    5) 关注点分离

    我不确定为什么FrontController 是从 ActionController 扩展而来的。没有其他类可以扩展它,但我想 FrontController 实例化的类也是 ActionController 的子类。但是 FrontController 虽然被命名为控制器,但做的事情与 PageControllers 不同,所以我可能会将它们分开。

    顺便说一句,如果您对提高代码质量感兴趣,请查看http://phpqatools.org/ 提供的幻灯片和工具

    【讨论】:

    • 我以为我遵守了 PEAR 约定。我在什么方面不是?感谢您的反馈!
    • 你会推荐哪些具体的缩短方法?
    • @Drew 比如开课后应该有缩进。函数和类定义中的花括号应从新行开始。私有成员,但不受保护,应该在前面加上一个下划线。您可以使用 PHP_CodeSniffer 查看它关闭的位置。
    【解决方案3】:

    你的代码很像CakePhp。我建议检查一下,它使用 App::import() 和一个包装文件系统的 File 类来完成所有这些工作。它由社区在不同版本和操作系统上进行了测试,实际上可以节省您的时间。

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 2023-03-06
      • 2021-10-20
      • 2019-12-02
      • 2018-09-09
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多