doushun1870 2011-10-04 16:38
浏览 24
已采纳

如何使用包含常用代码的代码块创建函数?

I have a do...while loop and a try...catch block that wraps around database centric code. The do...while and try...catch serves the purpose of preventing transaction deadlocks, and it does so very well from extensive testing. My problem now is code redundancy. I cannot figure out a way to deploy a function or method that performs the do...while and try...catch around a generic set of database centric code without using the "evil" eval command. I imagine this comes up under other software design pattern scenarios.

This illustrates how I imagine the method with eval:

class Database {
    public static function deadlockSafeTransaction($code) {
        do {
            // setup a condition
            try {
                // start transaction

                eval($code); //evil

                // commit transaction
            }
            catch(Exception $ex) {
                // rollback transaction
                // analyze exception for deadlock and adjust condition or rethrow exception
            }
        } while(condition);
    }
}

This illustrates an undesired coding practice if I were to use the method above:

// code

Database::deadlockSafeTransaction("
// code - sometimes a lot of complicated code with other method calls and loops
");

// code

I am looking for a solution that does not include the use of the eval command.

After writing all of this up, I just thought of the possibility of flanking my code with include statements:

include "do-try.php";
// database code
include "catch-while.php";

But I am looking for something more OOPish and less hackish. I don't even know if the above would work and the includes may carry an unnecessary performance expense. So the issue still warrants inquiry and discussion for the best solution.

  • 写回答

4条回答 默认 最新

  • doujiaci7976 2011-10-04 16:41
    关注

    Use callbacks:

     function doInTransaction($fn) {
    
         // stuff
    
         $fn();
    
         // more stuff
    
     }
    

    and then

     doInTransaction(function() {
    
       // whatever
    
     });
    

    As to the question how to pass the context into the function, I don't think using globals is a good idea. Much better is to pass what you need explicitly to the function:

    function doInTransaction($fn) {
    
        // stuff
    
        $fn($this->databaseConnection, $this->logFile);
    
        // more stuff
    }
    

    and the function should be prepared to accept what's gets passed to it:

    doInTransaction(function($connection, $logFile) {
    
        $x = $connection->xxxx
    
    })
    

    Even better option is to make function a Delegate and just give it the whole "parent" object:

    function doInTransaction($delegate) {
    
        // stuff
    
        $delegate($this);
    
        // more stuff
    }
    
    doInTransaction(function($dbObject) {
    
        $dbObject->doSomething(...);
    
    })
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用