足跡: 编程规范

编程规范

這是本文件的舊版!


本规范是非强制的,但强烈建议你遵守。

编程规范

为了能够配合既有代码使用,合理利用服务器资源,所有程序必须遵守本编程规范。

总旨

开放式电脑的程序需要基于事件驱动、能够“干净”地终止,做到低耦合高内聚、尽量运用库的功能,不要自己实现即有库已实现的功能。

具体来说,规则如下:

  • 非后台程序中,使用event.pull系列函数处理事件。只有后台程序才可以使用event.listen函数。
  • 无论是否为后台程序,键鼠事件必须使用event.pull系列函数处理。目的是为了退出程序后键鼠事件不再被处理。
  • 如无特殊要求,使用local变量和函数。
  • 必须能够处理interrupted事件,非后台程序中,处理的行为是注销所有事件、定时器、文件句柄等,然后退出整个程序;后台程序中,处理的行为是简单地退出。
  • 后台程序中,必须监听一个事件。该事件触发后能注销所有事件、定时器、文件句柄等,从而“干净”地退出后台程序。
  • 后台程序中,必须监听一个事件。该事件触发后能让后台程序恢复显示和处理键鼠事件。

示例

1.1 一个简单的前台程序

local timer = event.timer(1000, local function()  -- 定时器
    print("timer!");
end);
 
while true do
    local id, _, x, y = event.pullMultiple("touch", "interrupted");
    -- 中断事件
    if id == "interrupted" then
        print("soft interrupt! exiting...");
        event.cancel(timer);                -- 清理资源
        os.exit(0);                         -- 退出
    -- 点击事件
    elseif id == "touch" then
        print("user touched! x=", arg["x"], "; y=", arg["y"]);
    end
end

1.2 一个稍微复杂的前台程序

local timer = event.timer(1000, local function()  -- 定时器
    print("timer!");
end);
 
local ifTerminate = false;
while true do
    -- 处理事件
    event.pullFiltered(local function (ename, ...)
        local ename2handling = {
            -- 点击事件
            ["touch"] = local function()
                print("user touched! x=", arg["x"], "; y=", arg["y"]);
            end,
            -- 红石事件
            ["redstone_changed"] = local function()
                print("redstone changed! side=", arg["side"]);
            end,
            -- 中断事件
            ["interrupted"] = local function()
                print("soft interrupt! closing...");
                -- 这儿不能退出!在filter函数之中要返回true表示事件被处理了,然后在pullFiltered调用之外退出。
                ifTerminate = true;         -- 标记事件处理结束后退出
            end
        };
 
        if ename2handling[ename] then       -- 这个事件是我们想要处理的
            ename2handling[ename]();
            return true;
        else
            return false;
        end
    end);
 
    if ifTerminate then                     
        event.cancel(timer);                -- 清理资源
        os.exit(0);                         -- 退出
    end
end

2. 后台程序

在没有多任务操作系统的情况下编写在后台运行的程序是很麻烦、很原始的。您需要完全手动处理应用程序切入后台、恢复前台的所有逻辑,就如同在 DOS 中一样。在大部分时刻你不需要让多个程序同时在 opencomputers 上执行。因为 opencomputers 的主要目的是为工业控制以及自动化(即通常有一个固定的职责),而不是当作一个个人电脑来使用。

本代码没有经过实际测试,应该无法符合预期运作。本代码的作用仅仅是供您参考和学习操作系统原理,以及给予一个在OC中的bare bones的多任务的大致实现和思想。

local ifHide = false;                       -- 程序是否隐藏(后台运行)
local outputBuffer = "";                    -- 输出缓冲区
 
local timer = event.timer(1000, local function()  -- 定时器
    appPrint("timer!");
end);
 
local pullInputThread = nil;  -- 一个处理输入事件的“线程”——只执行一次的timer
 
local redstoneEventHandler = event.listen("redstone_changed", local function(addr, side)
    appPrint("redstone! addr=", addr, "; side=", side);
end);
 
-- 监听将程序至于后台/前台的键盘事件
local hideShowKeyEventHandler = event.listen("key_up", local function(addr, char)
    -- 如果按下小键盘0,唤起应用
    if char == keyboard.keys.numpad0 then
        show();
        event.push("hide_all_programs");        -- 通知其他程序隐藏自己
 
    -- 如果按下小键盘1,完全终止应用
    elseif char == keyboard.keys.numpad1 then
        terminate();
end);
 
-- 如果收到hide_all_programs信号,隐藏自己。
local hideAllProgramsEventHandler = event.listen("hide_all_programs", local function()
    hide();
end);
 
-- 将程序至于后台
function hide()
    ifHide = true;
    event.cancel(pullInputThread);  -- 强制终止正在执行的pullInput函数
    os.exit(0);                     -- 直接退出
end
 
-- 恢复程序于前台
function show()
    ifHide = false;
    dumpOutBuffer();                -- 将程序的输出dump到屏幕上
    pullInputThread = event.timer(0, pullInput, 1);    -- 执行pullInput“线程”
end
 
-- 完全终止程序
function terminate()
    event.cancel(timer);            -- 注销定时器
    event.ignore(redstoneEventHandler);     -- 注销红石事件回调
    event.ignore(hideShowKeyEventHandler);  -- 注销将程序至于后台/前台的回调
    event.ignore(hideAllProgramsEventHandler);  -- 注销hide_all_programs信号的回调
end
 
-- 打印
function appPrint(str)
    outputBuffer += str + "\n";
    if not ifHide then
        print(str);
    end
end
 
-- 在屏幕上显示输出buffer
function dumpOutBuffer()
    print(outputBuffer);
end
 
-- 处理键鼠事件
function pullInput()
    while true do
        if not ifHide then  -- 仅仅在程序不在后台时方处理键鼠事件
            local id, _, x, y = event.pullMultiple("touch", "interrupted");
            -- 中断事件
            if id == "interrupted" then
                appPrint("soft interrupt! hidding...");
                hide();
            elseif id == "touch" then
                appPrint("user touched! x=", arg["x"], "; y=", arg["y"]);
            end
        end
    end
end
 
-- main
show();
wiki/自动化与科技指导/opencomputers/编程规范.1702023601.txt.gz · 上一次變更: 2023/12/08 16:20 由 nikoqw
GNU Free Documentation License 1.3 若無特別註明,本 wiki 上的內容都是採用以下授權方式: GNU Free Documentation License 1.3