Một thay thế cho một loạt các chức năng?


0 Phiếu
Đã hỏi 20/5/2016 bởi CoccoWeb (120 điểm)
Tôi đang programming ứng dụng (php) mà yêu cầu một danh sách rất dài tương tự nhưng khác nhau chức năng, mà đang được gọi là bởi một tập hợp các phím :
$functions = [
    "do this" => function() {
        // does this
    },
    "do that" => function() {
        // does that
    }
] 
etc.
, tôi đã chọn để đặt các chức năng tương tự trong một mảng bởi vì họ không phải là tương tự như đủ - nhận được kết quả tương tự với một function lớn được đầy đủ các điều kiện báo cáo không phải là đi để làm việc. Và tôi cần để có thể gọi cho họ chỉ bằng chính , ví dụ:
$program = ["do this", "do that", "do this"];
foreach ($program as $k => $v) {
    $functions[$v]();
}
điều là chức năng-array structure này đang gây ra nhiều vấn đề, ví dụ: tôi có một thời gian khó gọi một mảng function từ trong vòng một mảng function , ví dụ như điều này không làm việc:
"do that" => function() {
    $functions["do this"]();
}
cũng không phải đây:
"do that" => function() {
    global $functions;
    $functions["do this"]();
}
hoặc này: tôi đoán tôi có thể có một function khổng lồ với một long switch statement
"do that" => function($functions) {
    $functions["do this"]();
}
$functions["do that"]($functions);
:
function similar_functions($key) {
    switch ($key) {
        case "do this":
            // does this
        break;
        case "do that":
            // does that
        break;
    }
}
, nhưng mà không thực sự có vẻ như thực hành tốt. Hoặc có lẽ nó? vì vậy, lựa chọn thay thế của tôi là gì? tôi có nên đi với cấu trúc switch ? Hoặc là có khác, giải pháp tốt hơn?

2 Câu trả lời

0 Phiếu
Đã trả lời 02/6/2016 bởi something (455,900 điểm)
Bạn có thể làm điều đó một cách sạch hơn, đó là, đóng gói tất cả các chức năng này vào một lớp học. Họ có thể là static hoặc năng động, nó không quan trọng nhiều tôi đoán trong trường hợp này. Tôi sẽ hiển thị cả hai ví dụ... 1. dynamic phương pháp tiếp cận
class MyFunctions
{
    public function doThis()
    {
        /* implement do this here */
    }
    public function doThat()
    {
        /* implement do that here */
    }
    /* ... */
}
/* then somewhere else */
$program = ["doThis", "doThat", "doThis"];
$myFunctions = new MyFunctions;
foreach ($program as $method) {
    $myFunctions->$method();
}
2. static phương pháp tiếp cận
class MyFunctions
{
    public static function doThis()
    {
        /* implement do this here */
    }
    public static function doThat()
    {
        /* implement do that here */
    }
    /* ... */
}
/* then somewhere else */
$program = ["doThis", "doThat", "doThis"];
foreach ($program as $method) {
    MyFunctions::$method();
}
IMHO đây là sạch hơn so với thực hiện những chức năng trong một loạt các đóng cửa... Và tốt hơn so với thực hiện một switch như bạn vẫn có thể gọi đây là trong một loop - vì vậy tại sao chậm với một switch?
0 Phiếu
Đã trả lời 02/6/2016 bởi Maliagagg (140 điểm)
Closures are expensive for performance and memoryusage in php. Procedural coding provoked a big ball of mud, spaghetti code and other anti patterns. Switch structures are very hard to test and it's a violation of OCP. You should prefer OOP in SOLID way to avoid redundancy, improving scalability and maintainablity. That is the best practice to provide a set of functions which are reuseable. You can also seperate your code in layers and modules to reduce complexity and improve interchangability. In your case your classes can implement __invoke to call it as invokable and your keys could be the fullqualified namespaces for these classes, so you can call it like a function. From now on you can also use inheritence, polymorphism or design patterns like composite, decorator etc. to reuse other functions or to add functions. Here a simple Example..
<?php
use Foo\\Bar;
class This
{
    public function __invoke()
    {
        $this->execute();
    }
    public function execute()
    {
        /* ... */
    }
 }
class That extends This
{
    public function execute()
    {
        /* ... */
    }
 }
$namespaces = array("\\Foo\\Bar\\This", "\\Foo\\Bar\\That"); 
foreach ($namespaces as $fullQualifiedNamespace) {
    /** @var callable $fullQualifiedNamespace */
    $fullQualifiedNamespace(); 
}
This behavior is also reachable by implementing a specific interface to This and That. Within iteration you can check the interface to call the defined contract. Or you build a Process Class where you can add objects which implements this interface. The Process class can execute all attached objects (Chain of Responsibility). I would prefer the Chain of Responsibility Pattern this is understandable by most developers and not so magic like PHP's __invoke interceptor. In a factory you can define your chain and you are able to define other dependencies to the chain or to the attached chain objects.
Đã bình luận 04/6/2016 bởi boris (270 điểm)
'kêu gọi một loạt các function từ trong vòng một mảng chức năng' sẽ không làm việc vì '$functions' sẽ chỉ được gán các giá trị sau khi hoàn toàn đánh giá RHS.

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...