【问题标题】:Avoiding Spaghetti Code避免意大利面条代码
【发布时间】:2015-12-16 15:46:27
【问题描述】:

我一直在阅读如何avoid spaghetti code in batch files

在意大利面条代码的例子中,我意识到我登录时使用的批处理文件几乎适合这个例子。有人可以帮我让我的批处理文件没有意大利面条代码吗?

@ECHO OFF
CLS


:MENU
echo Welcome %USERNAME%

echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit

SET /P M=Please Enter Selection, then Press Enter:

IF %M%==1 GOTO StarKeePass
IF %M%==2 GOTO Backup
IF %M%==3 GOTO FireFox
IF %M%==4 GOTO :EOF
GOTO MENU


:StarKeePass
SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"

echo I'll start KeePass for You
START "" %keePass% %kdb%

GOTO MENU

:Backup
SET backup="%USERPROFILE%\backup.bat"
call %backup%

GOTO MENU

:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe

GOTO MENU

【问题讨论】:

  • 这绝对不是意大利面条代码。例如,当函数调用在语法上嵌套太深或其他构造时,它被称为 SC,应该在逻辑上分组并分成多行。
  • @Ctx - 感谢您的澄清。所以,从表面上看,这很好,对吗?我有另一篇关于如何使它更健壮的帖子,但这是一个不同的问题。
  • 对我来说很好,是的

标签: batch-file command-line cmd


【解决方案1】:

在这种情况下,如果你想使用子程序,你应该这样做:

@ECHO OFF
CLS


:MENU
echo Welcome %USERNAME%

echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit

SET /P M=Please Enter Selection, then Press Enter:

IF %M%==1 CALL :StartKeePass
IF %M%==2 CALL :Backup
IF %M%==3 CALL :FireFox
IF %M%==4 GOTO :EOF
GOTO MENU


:StartKeePass
SET "keePass=%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET "kdb=%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"

echo I'll start KeePass for You
START "" %keePass% %kdb%

GOTO :EOF

:Backup
SET "backup=%USERPROFILE%\backup.bat"
call %backup%

GOTO :EOF

:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe

GOTO :EOF

请注意,我更改了一些内容。你应该使用call :labelgoto :eof/exit /b,而不是转到...转到菜单。除此之外,你有一个拼写错误 StartKeePass,而不是set variable="value",最好使用set "variable=value"。这也将接受值中的空格,但不会在变量中添加引号

下次你应该把它发到code review,因为这些东西并不是真正的错误

【讨论】:

  • 快速提问,为什么说 goto: eof 比 goto: menu 更好?
  • 为了解释它, call 临时给出在这个批处理文件中创建一个新的批处理文件,从给定的标签开始。当该批处理文件完成后,它会返回到调用行下的调用行。
  • goto :eof 并不是真的更好,但它是使用子例程的选择,或者只是不断地转到批处理文件中的位置。我建议查看here 以获得更好的解释
【解决方案2】:

如果您想完全删除gotos,您只需再次调用该脚本即可继续使用它。此外,如果您使用的 Windows 版本高于 XP,请查看 choice 命令,因为它无需检查用户是否输入了无效输入。

@echo off

cls
echo Welcome %USERNAME%

echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit

choice /C:1234 /M "Please enter your selection: " /N

:: The first option listed by choice's /C option will return an errorlevel value of 1, the second 2, and so on
if %errorlevel% equ 1 (
    SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
    SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"

    echo I'll start KeePass for You
    START "" %keePass% %kdb%
)

:: I've converted these to one-liners simply for personal preference.
:: You can keep these the way you had them if you put them inside of parentheses like with option 1.
if %errorlevel% equ 2 call "%USERPROFILE%\backup.bat"
if %errorlevel% equ 3 start "" "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
if %errorlevel% equ 4 exit /b

:: Calls this script again, simulating a goto :MENU
:: Personally, I'd stick with a label and a goto in this instance,
:: but this is how you could do it if you don't want to use goto at all
call %0

如果用户可以做出的每个选择都相当简单(即可以简化为一两个命令),您可能希望这样编写代码;否则,请务必使用 Dennis 建议的子程序。

【讨论】:

    【解决方案3】:

    我对组织这一点的看法,添加了对m 变量的重置,允许处理一些意外输入,并将其全部检查到一个代码块中。

    “Dennis van Gils”的回答没有错,我想我会向您展示一种不同的方法。

    @echo off
    setlocal enableDelayedExpansion
    
    :menu
    set "m="
    cls
    echo/Welcome !username!
    echo/
    echo/1 - Start keepass
    echo/2 - Backup
    echo/3 - Firefox
    echo/4 - Exit
    echo/
    set /p "m=Please enter selection, then press enter:"
    if not defined m (
        cls
        echo/Error: Empty input.
        pause
    ) else (
        if "!m!" equ "1" (
            set "keepass=!userprofile!\keepass\keepass-2.30\keepass.exe"
            set "kdb=!userprofile!\keepass\passworddatabase\passworddatabase.kdbx"
            echo/I'll start keepass for you
            start "" !keepass! !kdb!
        ) else (
            if "!m!" equ "2" (
                set "backup=!userprofile!\backup.bat"
                call !backup!
            ) else (
                if "!m!" equ "3" (
                    cd "c:\program files (x86)\mozilla firefox\"
                    start firefox.exe
                ) else (
                    if "!m!" equ "4" (
                        goto :eof
                    ) else (
                        cls
                        echo/Error: ["!m!"] not recognized.
                        pause
                    )
                )
            )
        )
    )
    goto :menu
    

    注意:echo/ 是一种习惯,因为 echo:echo\ 我误认为是文件路径/url 的一部分,而 echo. 因其较长的命令时间而备受关注。

    另外,我更喜欢使用! 而不是% 以及setlocal enableDelayedExpansion 纯粹的偏好,并且易于块编码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      相关资源
      最近更新 更多