প্রধান () সংক্ষিপ্ত হওয়া উচিত কেন?


87

আমি 9 বছরেরও বেশি সময় ধরে প্রোগ্রামিং করে চলেছি এবং আমার প্রথম প্রোগ্রামিং শিক্ষকের পরামর্শ অনুসারে আমি সর্বদা আমার main()ফাংশনটিকে খুব সংক্ষিপ্ত রাখি ।

প্রথমে আমার ধারণা ছিল না কেন। আমি কেবল না বুঝে মেনে চললাম, আমার অধ্যাপকদের আনন্দের বিষয়।

অভিজ্ঞতা অর্জনের পরে, আমি বুঝতে পেরেছি যে আমি যদি আমার কোডটি সঠিকভাবে ডিজাইন করি তবে একটি সংক্ষিপ্ত main()ফাংশন হ'ল সামান্য ঘটনা ঘটবে। মডুলারাইজড কোড লেখার এবং একক দায়িত্বের নীতি অনুসরণ করে আমার কোডটিকে "গুচ্ছগুলিতে" ডিজাইনের অনুমতি দেওয়া হয়েছিল এবং main()প্রোগ্রামটি চালু হওয়ার জন্য অনুঘটক ছাড়া আর কিছুই নয়।

কয়েক সপ্তাহ আগে দ্রুত, আমি পাইথনের স্যুস কোডটি দেখছিলাম এবং আমি main()ফাংশনটি পেয়েছি :

/* Minimal main program -- everything is loaded from the library */

...

int
main(int argc, char **argv)
{
    ...
    return Py_Main(argc, argv);
}

ইয়ে পাইথন। সংক্ষিপ্ত main()ফাংশন == ভাল কোড।

প্রোগ্রামিং শিক্ষকরা ঠিক বলেছেন।

আরও গভীর করে দেখতে চাই, আমি পাই_মাইনের দিকে একবার তাকালাম। সম্পূর্ণরূপে, এটি নিম্নলিখিত হিসাবে সংজ্ঞায়িত করা হয়েছে:

/* Main program */

int
Py_Main(int argc, char **argv)
{
    int c;
    int sts;
    char *command = NULL;
    char *filename = NULL;
    char *module = NULL;
    FILE *fp = stdin;
    char *p;
    int unbuffered = 0;
    int skipfirstline = 0;
    int stdin_is_interactive = 0;
    int help = 0;
    int version = 0;
    int saw_unbuffered_flag = 0;
    PyCompilerFlags cf;

    cf.cf_flags = 0;

    orig_argc = argc;           /* For Py_GetArgcArgv() */
    orig_argv = argv;

#ifdef RISCOS
    Py_RISCOSWimpFlag = 0;
#endif

    PySys_ResetWarnOptions();

    while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
        if (c == 'c') {
            /* -c is the last option; following arguments
               that look like options are left for the
               command to interpret. */
            command = (char *)malloc(strlen(_PyOS_optarg) + 2);
            if (command == NULL)
                Py_FatalError(
                   "not enough memory to copy -c argument");
            strcpy(command, _PyOS_optarg);
            strcat(command, "\n");
            break;
        }

        if (c == 'm') {
            /* -m is the last option; following arguments
               that look like options are left for the
               module to interpret. */
            module = (char *)malloc(strlen(_PyOS_optarg) + 2);
            if (module == NULL)
                Py_FatalError(
                   "not enough memory to copy -m argument");
            strcpy(module, _PyOS_optarg);
            break;
        }

        switch (c) {
        case 'b':
            Py_BytesWarningFlag++;
            break;

        case 'd':
            Py_DebugFlag++;
            break;

        case '3':
            Py_Py3kWarningFlag++;
            if (!Py_DivisionWarningFlag)
                Py_DivisionWarningFlag = 1;
            break;

        case 'Q':
            if (strcmp(_PyOS_optarg, "old") == 0) {
                Py_DivisionWarningFlag = 0;
                break;
            }
            if (strcmp(_PyOS_optarg, "warn") == 0) {
                Py_DivisionWarningFlag = 1;
                break;
            }
            if (strcmp(_PyOS_optarg, "warnall") == 0) {
                Py_DivisionWarningFlag = 2;
                break;
            }
            if (strcmp(_PyOS_optarg, "new") == 0) {
                /* This only affects __main__ */
                cf.cf_flags |= CO_FUTURE_DIVISION;
                /* And this tells the eval loop to treat
                   BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
                _Py_QnewFlag = 1;
                break;
            }
            fprintf(stderr,
                "-Q option should be `-Qold', "
                "`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
            return usage(2, argv[0]);
            /* NOTREACHED */

        case 'i':
            Py_InspectFlag++;
            Py_InteractiveFlag++;
            break;

        /* case 'J': reserved for Jython */

        case 'O':
            Py_OptimizeFlag++;
            break;

        case 'B':
            Py_DontWriteBytecodeFlag++;
            break;

        case 's':
            Py_NoUserSiteDirectory++;
            break;

        case 'S':
            Py_NoSiteFlag++;
            break;

        case 'E':
            Py_IgnoreEnvironmentFlag++;
            break;

        case 't':
            Py_TabcheckFlag++;
            break;

        case 'u':
            unbuffered++;
            saw_unbuffered_flag = 1;
            break;

        case 'v':
            Py_VerboseFlag++;
            break;

#ifdef RISCOS
        case 'w':
            Py_RISCOSWimpFlag = 1;
            break;
#endif

        case 'x':
            skipfirstline = 1;
            break;

        /* case 'X': reserved for implementation-specific arguments */

        case 'U':
            Py_UnicodeFlag++;
            break;
        case 'h':
        case '?':
            help++;
            break;
        case 'V':
            version++;
            break;

        case 'W':
            PySys_AddWarnOption(_PyOS_optarg);
            break;

        /* This space reserved for other options */

        default:
            return usage(2, argv[0]);
            /*NOTREACHED*/

        }
    }

    if (help)
        return usage(0, argv[0]);

    if (version) {
        fprintf(stderr, "Python %s\n", PY_VERSION);
        return 0;
    }

    if (Py_Py3kWarningFlag && !Py_TabcheckFlag)
        /* -3 implies -t (but not -tt) */
        Py_TabcheckFlag = 1;

    if (!Py_InspectFlag &&
        (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
        Py_InspectFlag = 1;
    if (!saw_unbuffered_flag &&
        (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
        unbuffered = 1;

    if (!Py_NoUserSiteDirectory &&
        (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
        Py_NoUserSiteDirectory = 1;

    if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
        char *buf, *warning;

        buf = (char *)malloc(strlen(p) + 1);
        if (buf == NULL)
            Py_FatalError(
               "not enough memory to copy PYTHONWARNINGS");
        strcpy(buf, p);
        for (warning = strtok(buf, ",");
             warning != NULL;
             warning = strtok(NULL, ","))
            PySys_AddWarnOption(warning);
        free(buf);
    }

    if (command == NULL && module == NULL && _PyOS_optind < argc &&
        strcmp(argv[_PyOS_optind], "-") != 0)
    {
#ifdef __VMS
        filename = decc$translate_vms(argv[_PyOS_optind]);
        if (filename == (char *)0 || filename == (char *)-1)
            filename = argv[_PyOS_optind];

#else
        filename = argv[_PyOS_optind];
#endif
    }

    stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);

    if (unbuffered) {
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
        _setmode(fileno(stdin), O_BINARY);
        _setmode(fileno(stdout), O_BINARY);
#endif
#ifdef HAVE_SETVBUF
        setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
        setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
#else /* !HAVE_SETVBUF */
        setbuf(stdin,  (char *)NULL);
        setbuf(stdout, (char *)NULL);
        setbuf(stderr, (char *)NULL);
#endif /* !HAVE_SETVBUF */
    }
    else if (Py_InteractiveFlag) {
#ifdef MS_WINDOWS
        /* Doesn't have to have line-buffered -- use unbuffered */
        /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
#else /* !MS_WINDOWS */
#ifdef HAVE_SETVBUF
        setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
        setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
#endif /* HAVE_SETVBUF */
#endif /* !MS_WINDOWS */
        /* Leave stderr alone - it should be unbuffered anyway. */
    }
#ifdef __VMS
    else {
        setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
    }
#endif /* __VMS */

#ifdef __APPLE__
    /* On MacOS X, when the Python interpreter is embedded in an
       application bundle, it gets executed by a bootstrapping script
       that does os.execve() with an argv[0] that's different from the
       actual Python executable. This is needed to keep the Finder happy,
       or rather, to work around Apple's overly strict requirements of
       the process name. However, we still need a usable sys.executable,
       so the actual executable path is passed in an environment variable.
       See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
       script. */
    if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0')
        Py_SetProgramName(p);
    else
        Py_SetProgramName(argv[0]);
#else
    Py_SetProgramName(argv[0]);
#endif
    Py_Initialize();

    if (Py_VerboseFlag ||
        (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
        fprintf(stderr, "Python %s on %s\n",
            Py_GetVersion(), Py_GetPlatform());
        if (!Py_NoSiteFlag)
            fprintf(stderr, "%s\n", COPYRIGHT);
    }

    if (command != NULL) {
        /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
        _PyOS_optind--;
        argv[_PyOS_optind] = "-c";
    }

    if (module != NULL) {
        /* Backup _PyOS_optind and force sys.argv[0] = '-c'
           so that PySys_SetArgv correctly sets sys.path[0] to ''
           rather than looking for a file called "-m". See
           tracker issue #8202 for details. */
        _PyOS_optind--;
        argv[_PyOS_optind] = "-c";
    }

    PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);

    if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
        isatty(fileno(stdin))) {
        PyObject *v;
        v = PyImport_ImportModule("readline");
        if (v == NULL)
            PyErr_Clear();
        else
            Py_DECREF(v);
    }

    if (command) {
        sts = PyRun_SimpleStringFlags(command, &cf) != 0;
        free(command);
    } else if (module) {
        sts = RunModule(module, 1);
        free(module);
    }
    else {

        if (filename == NULL && stdin_is_interactive) {
            Py_InspectFlag = 0; /* do exit on SystemExit */
            RunStartupFile(&cf);
        }
        /* XXX */

        sts = -1;               /* keep track of whether we've already run __main__ */

        if (filename != NULL) {
            sts = RunMainFromImporter(filename);
        }

        if (sts==-1 && filename!=NULL) {
            if ((fp = fopen(filename, "r")) == NULL) {
                fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
                    argv[0], filename, errno, strerror(errno));

                return 2;
            }
            else if (skipfirstline) {
                int ch;
                /* Push back first newline so line numbers
                   remain the same */
                while ((ch = getc(fp)) != EOF) {
                    if (ch == '\n') {
                        (void)ungetc(ch, fp);
                        break;
                    }
                }
            }
            {
                /* XXX: does this work on Win/Win64? (see posix_fstat) */
                struct stat sb;
                if (fstat(fileno(fp), &sb) == 0 &&
                    S_ISDIR(sb.st_mode)) {
                    fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
                    fclose(fp);
                    return 1;
                }
            }
        }

        if (sts==-1) {
            /* call pending calls like signal handlers (SIGINT) */
            if (Py_MakePendingCalls() == -1) {
                PyErr_Print();
                sts = 1;
            } else {
                sts = PyRun_AnyFileExFlags(
                    fp,
                    filename == NULL ? "<stdin>" : filename,
                    filename != NULL, &cf) != 0;
            }
        }

    }

    /* Check this environment variable at the end, to give programs the
     * opportunity to set it from Python.
     */
    if (!Py_InspectFlag &&
        (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
    {
        Py_InspectFlag = 1;
    }

    if (Py_InspectFlag && stdin_is_interactive &&
        (filename != NULL || command != NULL || module != NULL)) {
        Py_InspectFlag = 0;
        /* XXX */
        sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
    }

    Py_Finalize();
#ifdef RISCOS
    if (Py_RISCOSWimpFlag)
        fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
#endif

#ifdef __INSURE__
    /* Insure++ is a memory analysis tool that aids in discovering
     * memory leaks and other memory problems.  On Python exit, the
     * interned string dictionary is flagged as being in use at exit
     * (which it is).  Under normal circumstances, this is fine because
     * the memory will be automatically reclaimed by the system.  Under
     * memory debugging, it's a huge source of useless noise, so we
     * trade off slower shutdown for less distraction in the memory
     * reports.  -baw
     */
    _Py_ReleaseInternedStrings();
#endif /* __INSURE__ */

    return sts;
}

ভাল Godশ্বর সর্বশক্তিমান ... টাইটানিক ডুবিয়ে ফেলার পক্ষে এটি যথেষ্ট বড়।

দেখে মনে হচ্ছে পাইথন "ইন্ট্রো টু প্রোগ্রামিং ১০১" কৌশলটি করেছিল এবং স্রেফ এর সমস্ত কোডকে main()একটি অন্য ফাংশনে সরিয়ে নিয়েছিল যাকে একে "মেইন" এর সাথে খুব মিল বলে।

এখানে আমার প্রশ্ন: এই কোডটি কি ভয়ঙ্করভাবে লেখা হয়েছে, বা একটি সংক্ষিপ্ত প্রধান ফাংশন থাকার অন্যান্য কারণ রয়েছে?

যেহেতু এটি এখনই দাঁড়িয়ে আছে, আমি এটি করার সাথে সাথে কোডটিকে Py_Main()পিছনে সরিয়ে নিয়ে একেবারে কোনও পার্থক্য দেখছি না main()। আমি কি এই ভেবে ভুল করছি?


4
কোডরিভিউ.স্ট্যাকেক্সেক্সঞ্জ.কমের জন্য এটি কি আরও ভাল হবে না ?
foobar

38
@ লুজিন, না আমি কাউকে পাইথনের উত্স কোড পর্যালোচনা করতে বলছি না। এটি প্রোগ্রামিং প্রশ্ন।
রিওয়ালক

3
টিবিএইচ, অর্ধেক কোডটি অপশন প্রক্রিয়াজাতকরণ, এবং যে কোনও সময় আপনার প্রোগ্রামটি প্রচুর বিকল্পের সমর্থন করে এবং আপনি একটি কাস্টম প্রসেসর লিখেন, এটিই আপনি শেষ করছেন ...
নিম

7
@ স্টার নো, প্রোগ্রামারস.এসই সর্বোত্তম অনুশীলন, কোডিং শৈলী ইত্যাদির জন্যও আছে বাস্তবে, আমি এই সাইটের জন্য যাচ্ছি visit
মতিন উলহাক

4
@Nim, আমি বুঝতে এটি কি করছে, কিন্তু যেমন লিখতে না কোনো কারণ নেই options = ParseOptionFlags(argc,argv)যেখানে optionsএকটি হল structযে ভেরিয়েবল রয়েছে Py_BytesWarningFlag, Py_DebugFlag, ইত্যাদি ...
riwalk

উত্তর:


137

আপনি mainকোনও লাইব্রেরি থেকে রফতানি করতে পারবেন না , তবে আপনি রফতানি করতে পারবেন Py_Mainএবং তারপরে যে লাইব্রেরিটি ব্যবহার করছেন কেউ একই প্রোগ্রামে বিভিন্ন যুক্তি দিয়ে পাইথনকে "কল" করতে পারেন। এই মুহূর্তে, pythonগ্রন্থাগারের কেবল অন্য গ্রাহক হয়ে ওঠে, গ্রন্থাগারের ফাংশনটির জন্য একটি র‌্যাপারের চেয়ে সামান্য কিছু; এটি Py_Mainঅন্য সবার মতোই কল করে ।


1
একটি ভাল উত্তর আছে।
রিওয়ালক

26
আমি অনুমান করি যে আপনি এটি আমদানি করতে পারবেন না এটি বলার চেয়ে আরও সঠিক হতে পারে , @ শুশ। সি ++ স্ট্যান্ডার্ড এটিকে আপনার নিজের কোড থেকে কল করতে নিষেধ করেছে। এছাড়াও, এর সংযোগটি বাস্তবায়ন-সংজ্ঞায়িত। এছাড়াও, mainকার্যকরভাবে কলগুলি থেকে ফিরে আসা exit, যা আপনি সাধারণত কোনও লাইব্রেরি করতে চান না।
রব কেনেডি

3
@ কোডার, সি ++ 03 §3.6.1 / 5 দেখুন: "একটি রিটার্ন বিবৃতিতে mainমূল ফাংশনটি ছেড়ে যাওয়ার ... এবং exitআর্গুমেন্ট হিসাবে রিটার্ন মান সহ কল করার প্রভাব রয়েছে ।" এছাড়াও §18.3 / 8, যা ব্যাখ্যা করেছেন যে এবং "সব খোলা সি স্ট্রিম ... রাঙা হয়" আপনি কল যখন "স্ট্যাটিক স্টোরেজ সময়কাল ধ্বংস করে দেওয়া হয় অবজেক্টের" দেখুন exit। C99 এর অনুরূপ ভাষা রয়েছে।
রব কেনেডি

1
@ কোডার, exitপাতাগুলি mainঅপ্রাসঙ্গিক কিনা । আমরা এর আচরণ নিয়ে আলোচনা করছি না exit। আমরা এর আচরণ নিয়ে আলোচনা করছি main। এবং এর আচরণের মধ্যে main রয়েছেexit যা কিছু হতে পারে তার আচরণ অন্তর্ভুক্তএটিই আমদানি করা এবং কল করা অনাকাঙ্ক্ষিত করে তোলে main(যদি এমন কোনও কাজ করা এমনকি সম্ভব বা অনুমোদিতও হয়)।
রব কেনেডি

3
@ কোডার, যদি ফিরে এসে আপনার সংকলককে mainকল করার প্রভাব না ফেলে exit, তবে আপনার সংকলক মানটি অনুসরণ করে না। মান এধরনের আচরণ dictates যে জন্য mainপ্রমাণ যে হয় কিছু এটা সম্পর্কে বিশেষ। বিশেষ বিষয়টি mainএটি থেকে ফিরে আসার কল করার প্রভাব রয়েছে exit। ( এটি কীভাবে লেখকদের সংকলনের উপর নির্ভর করে The সংকলকটি কেবল ফাংশন শিরোনামে কোডটি সন্নিবেশ করতে পারে যা স্থির বস্তুগুলি ধ্বংস করে, atexitরুটিনগুলিকে কল করে , ফাইলগুলি ফ্লাশ করে এবং প্রোগ্রামটি সমাপ্ত করে - যা আবার কোনও লাইব্রেরিতে আপনি চান এমন কিছু নয়) ।)
রব কেনেডি

42

এটি mainএত দীর্ঘ হওয়া উচিত নয় যেহেতু আপনার কোনও ক্রিয়াকলাপ দীর্ঘ হওয়া উচিত নয় । mainফাংশন কেবল একটি বিশেষ ক্ষেত্রে। দীর্ঘ ক্রিয়াকলাপগুলি আঁকড়ে ধরা, রক্ষণাবেক্ষণযোগ্যতা হ্রাস এবং খুব সহজেই কাজ করা আরও কঠিন। ফাংশন (এবং main) খাটো রেখে আপনি সাধারণত আপনার কোডের মান উন্নত করেন।

আপনার উদাহরণে কোডটি সরিয়ে নিয়ে যাওয়ার কোনও লাভ নেই main


9
সোনার শব্দটি হতে পারে "পুনরায় ব্যবহার"। একটি দীর্ঘ mainখুব পুনরায় ব্যবহারযোগ্য নয়।
এস .লট

1
@ এস - এটি একটি সোনালি শব্দ। আরেকটি হলেন ওএমজি !!! এডিএইচডি শুধু লাথি মেরে !!!! বা সাধারণ পদ: শর্তাবলী ibility
এডওয়ার্ড স্ট্রেঞ্জ

3
মেইন () এর কিছু ফাংশনও থাকে না যা অন্যান্য ফাংশনগুলিতে নেই।
মার্টিন ইয়র্ক

1
এছাড়াও প্রধান () এর কোনও আসল অর্থ নেই। আপনার কোডগুলির অর্থ অন্য কোনও প্রোগ্রামারকে কিছু বোঝানো উচিত। আমি আর্গুমেন্টগুলি পার্স করতে প্রধান ব্যবহার করি এবং এটিই - এবং এমনকি আমি এটি পেশ করি যে এটি যদি কয়েক লাইনের বেশি হয়।
বিল কে

@ বিল কে: গুড পয়েন্ট, মূল () ব্যবহার করে কেবল যুক্তি বিশ্লেষণ করতে (এবং বাকি প্রোগ্রামটি শুরু করে) একক-দায়িত্বের নীতির সাথেও মেনে চলে।
জর্জিও

28

main()সংক্ষিপ্ত করার একটি কারণ ইউনিট পরীক্ষার সাথে জড়িত। main()এটিই এমন একটি ফাংশন যা ইউনিট পরীক্ষিত হতে পারে না, তাই আচরণের সিংহভাগটিকে অন্য শ্রেণিতে পরীক্ষা করা যায় যা ইউনিট পরীক্ষিত হতে পারে। আপনি যা বলেছিলেন তার সাথে এটিও যায়

মডুলারাইজড কোড লেখার এবং একক দায়িত্বের নীতি অনুসরণ করে আমার কোডটিকে "গুচ্ছগুলিতে" নকশার অনুমতি দেওয়া হয়েছিল এবং মূল () প্রোগ্রামটি চালু হওয়ার জন্য অনুঘটক ছাড়া আর কিছুই নয়।

দ্রষ্টব্য: আমি থেকে ধারণা পেয়েছেন এখানে


আরেকটি ভাল। কখনই সেই দিকটি ভাবেননি।
রিওয়ালক

16

mainদীর্ঘ হওয়ার জন্য এটি খুব কমই ভাল ধারণা ; যে কোনও ফাংশন (বা পদ্ধতি) এর মতো যদি এটি দীর্ঘ হয় তবে আপনি সম্ভবত পুনর্নির্মাণের সুযোগগুলি হারিয়েছেন।

আপনি উপরে উল্লিখিত নির্দিষ্ট ক্ষেত্রে mainসংক্ষিপ্ত কারণ এই সমস্ত জটিলতা প্রকট হয়ে উঠেছে Py_Main; যদি আপনি চান যে আপনার কোডটি একটি অজগর শেলের মতো আচরণ করতে পারে তবে আপনি খুব সহজেই এই শব্দটি চারপাশে বিচলিত না করে ব্যবহার করতে পারেন। (এটি এরকমভাবে যুক্ত হতে হবে কারণ mainআপনি কোনও লাইব্রেরিতে রাখলে এটি ভাল কাজ করে না ; যদি আপনি করেন তবে অদ্ভুত জিনিস ঘটে))

সম্পাদনা:
স্পষ্ট করার জন্য, mainকোনও স্থির লাইব্রেরিতে থাকতে পারে না কারণ এর সাথে এর কোনও সুস্পষ্ট লিঙ্ক নেই এবং তাই সঠিকভাবে সংযুক্ত করা হবে না (যদি না আপনি কোনও বস্তুর ফাইলে উল্লেখ না করে এমন কিছু সংগ্রহ না করেন যা কেবল ভয়ঙ্কর) ভাগ করা লাইব্রেরিগুলি সাধারণত একইরূপে গণ্য হয় (আবার বিভ্রান্তি রোধ করতে) যদিও অনেক প্ল্যাটফর্মে অতিরিক্ত ফ্যাক্টর হ'ল একটি ভাগ করা লাইব্রেরি বুটস্ট্র্যাপ বিভাগ mainব্যতীত কেবলমাত্র কার্যকর হয় (যার মধ্যে কেবল শেষ এবং সর্বাধিক দৃশ্যমান অংশ) )।


1
সংক্ষেপে, mainকোনও লাইব্রেরিতে রাখবেন না। এটি হয় কাজ করবে না এটি আপনাকে ভয়ঙ্করভাবে বিভ্রান্ত করবে। কিন্তু একটি ফাংশন যে কার্যত সব তার কাজ প্রতিনিধিরূপে হয় একটি liberal এর সংক্ষিপ্ত রূপ, যে প্রায়ই যুক্তিসম্মত নয়।
ডোনাল ফেলো

6

প্রধান কোনও কারণেই সংক্ষিপ্ত হওয়া উচিত যে কোনও ফাংশন সংক্ষিপ্ত হওয়া উচিত। মানব মস্তিষ্কে এক সাথে একবারে প্রচুর পরিমাণে অবিভাজনিত ডেটা মেমরিতে রাখা শক্ত হয়। এটিকে যৌক্তিক অংশগুলিতে ভাঙ্গুন যাতে অন্যান্য বিকাশকারীদের পক্ষে (পাশাপাশি নিজেকেও!) হজম করা এবং এর বিষয়ে যুক্তি করা সহজ হয়।

এবং হ্যাঁ, আপনার উদাহরণটি ভয়াবহ এবং পড়ার পক্ষে কঠিন, বজায় রাখা যাক।


হ্যাঁ আমি সর্বদা সন্দেহ করেছিলাম যে কোডটি নিজেই ভয়ানক ছিল (যদিও প্রশ্নটি কোডটির সাথে সম্পর্কিত নয়, কোডটি নিজেই কোড করে)। আমি আশঙ্কা করি যে পাইথনের আমার দৃষ্টিভঙ্গি ফলস্বরূপ সহজাতভাবে ক্ষতিগ্রস্থ হয়েছে ...
রিওয়ালক

1
@ স্টারগাজার: আমি জানি না যে কোডটি নিজেই ভয়াবহ, ঠিক যেহেতু এটি মানুষের ব্যবহারের জন্য সুসংহত নয়। এটি বলেছিল যে এখানে প্রচুর "কুৎসিত" কোড রয়েছে যা ভালভাবে কাজ করে এবং দুর্দান্ত অভিনয় করে। কোড সৌন্দর্য সবকিছু নয়, যদিও আমাদের সর্বদা সর্বোত্তম চেষ্টা করা উচিত সর্বোত্তমতম কোডটি লিখতে।
এড এস

Meh। আমার কাছে তারা এক এবং অভিন্ন। ক্লিন কোডটি আরও স্থিতিশীল হতে থাকে।
রিওয়ালক

কোডটি ভয়াবহ নয়, মূলত সুইচ কেস এবং একাধিক প্ল্যাটফর্ম হ্যান্ডলিং রয়েছে। আপনি ঠিক কি ভয়ানক মনে হয়?
ফ্রান্সেসকো

@ ফ্রান্সেসকো: দুঃখিত, রক্ষণাবেক্ষণ এবং পাঠযোগ্যতার দৃষ্টিকোণ থেকে "ভয়ঙ্কর", কার্যকরী নয়।
এড এস

1

কিছু লোক 50+ ফাংশন উপভোগ করে যা অন্য কিছুই করে না, তবে অন্য ফাংশনে কলটি মোড়ক করে। আমি বরং সাধারণ প্রোগ্রামটিই পছন্দ করব যা মূল প্রোগ্রামটির যুক্তিযুক্ত। অবশ্যই কাঠামোগত।

int main()
{
CheckInstanceCountAndRegister();
InitGlobals();
ProcessCmdParams();
DoInitialization();
ProgramMainLoopOrSomething();
DeInit();
ClearGlobals();
UnregisterInstance();
return 0; //ToMainCRTStartup which cleans heap, etc.
}

আমার কেন কোনও মোড়কের ভিতরে গুটিয়ে রাখা উচিত তার কোনও কারণ আমি দেখতে পাচ্ছি না।

এটি নিখুঁতভাবে ব্যক্তিগত স্বাদ।


1
কারণ এটি নথির কোড। আপনি প্রায় কোনও মন্তব্য লেখার প্রয়োজন ছাড়াই এইভাবে কোড লিখতে পারেন। এবং আপনি কোডটি পরিবর্তন করলে ডকুমেন্টেশন স্বয়ংক্রিয়ভাবে পরিবর্তন করে :-)।
অলিভার ওয়েইলার

1

কেবলমাত্র মূল নয়, আপনার সমস্ত ফাংশনকে সংক্ষিপ্ত রাখার সর্বোত্তম অনুশীলন। তবে "সংক্ষিপ্ত" বিষয়গত, এটি আপনার প্রোগ্রামের আকার এবং আপনি যে ভাষাটি ব্যবহার করছেন তার উপর নির্ভর করে।


0

mainকোডিং মান ছাড়া অন্য যে কোনও দৈর্ঘ্যের হওয়ার প্রয়োজন নেই। mainঅন্য যে কোনও একটি ফাংশন এবং এর জটিলতা 10 এর নীচে হওয়া উচিত (বা আপনার কোডিং মানগুলি যাই বলুক না কেন)। এটাই, অন্য যে কোনও কিছু বরং তর্কযোগ্য।

সম্পাদন করা

mainসংক্ষিপ্ত হওয়া উচিত নয়। বা দীর্ঘ। এটি আপনার নকশার উপর ভিত্তি করে সঞ্চালনের জন্য প্রয়োজনীয় কার্যকারিতা অন্তর্ভুক্ত করা উচিত এবং কোডিং মানগুলি মেনে চলা উচিত।

আপনার প্রশ্নের নির্দিষ্ট কোড হিসাবে - হ্যাঁ, এটি কুরুচিপূর্ণ।

আপনার দ্বিতীয় প্রশ্ন হিসাবে - হ্যাঁ, আপনি ভুল । সমস্ত কোডটি আবার মূলতে সরিয়ে নেওয়া আপনাকে Py_Mainবাইরের সাথে সংযুক্ত করে একটি লাইব্রেরি হিসাবে মডুলারিটি ব্যবহার করতে দেয় না ।

এখন আমি কি পরিষ্কার?


আমি দীর্ঘ জিজ্ঞাসা করতে পারি না । আমি জিজ্ঞাসা করলাম কেন এটি দীর্ঘ হওয়া উচিত নয়
রিওয়ালক

"10 এর নিচে জটিলতা"? তার জন্য কি কোনও পরিমাপের ইউনিট আছে?
ডোনাল ফেলো

@ স্টারগাজের 712 ফাংশনের দৈর্ঘ্য সাধারণত কোডিং মান দ্বারা নিয়ন্ত্রিত হয়। এটি একটি পঠনযোগ্যতা ইস্যু (এবং জটিলতা, সাধারণত দীর্ঘ ফাংশনগুলি ব্রাঞ্চ করা হয় যাতে জটিলতাটি ২০ এর উপরে হয়), এবং যেমনটি আমি বলেছি - mainএই ক্ষেত্রে অন্য কোনও কার্যক্রমে আলাদা নয়।
littleadv

@ ডোনাল - হ্যাঁ, লিঙ্কটি ক্লিক করুন।
littleadv

আমি এই এক কুঁড়ি ডাউন করতে হবে। আপনি প্রশ্নের অভিপ্রায়টি পুরোপুরি অনুপস্থিত।
রিওয়ালক

0

এখানে একটি নতুন ব্যবহারিক কারণ জিসিসি থেকে 4..6.১ চেঞ্জলগ থেকে মূল সংক্ষেপণ রাখুন :

নামযুক্ত বিভাগ সমর্থন সহ বেশিরভাগ লক্ষ্যবস্তুগুলিতে, কেবলমাত্র প্রারম্ভকালে (স্ট্যাটিক কনস্ট্রাক্টর এবং প্রধান ) ফাংশনগুলি ব্যবহৃত হয়, কেবল প্রস্থান করার সময় ব্যবহৃত ফাংশন এবং ঠান্ডা সনাক্তকারী ফাংশনগুলি পৃথক পাঠ্য বিভাগের সাবসেকশনগুলিতে স্থাপন করা হয় । এটি -ফ্রেডার-ফাংশন বৈশিষ্ট্যটি প্রসারিত করে এবং একই স্যুইচ দ্বারা নিয়ন্ত্রিত হয়। লক্ষ্যটি হ'ল বড় সি ++ প্রোগ্রামের প্রারম্ভকালীন সময়ের উন্নতি করা।

হাইলাইটিং আমার দ্বারা যোগ করা।


0

ধরে নিবেন না যে কেবলমাত্র সেই সফ্টওয়্যারটির পিছনে থাকা সমস্ত কোডই ভাল software ভাল সফ্টওয়্যার এবং ভাল কোড একই জিনিস নয় এবং এমনকি যেখানে ভাল সফ্টওয়্যারকে ভাল কোড দ্বারা সমর্থন করা হয়, এটি অবশ্যম্ভাবী যে একটি বড় প্রকল্পে এমন জায়গা থাকবে যেখানে মানগুলি পিছলে যায়।

একটি সংক্ষিপ্ত mainফাংশন থাকা ভাল অনুশীলন , তবে এটি সাধারণ নিয়মের কেবল একটি বিশেষ ঘটনা যে সংক্ষিপ্ত ফাংশনগুলি থাকা ভাল। সংক্ষিপ্ত ফাংশনগুলি বুঝতে সহজতর এবং ডিবাগ করা সহজ এবং সেইসাথে 'একক উদ্দেশ্য' ডিজাইনের ধরণের সাথে আঁকানো আরও ভাল যা প্রোগ্রামগুলিকে আরও ভাববান করে তোলে। mainসম্ভবত, নিয়মটি আঁকানোর আরও গুরুত্বপূর্ণ জায়গা যেহেতু যে কেউ প্রোগ্রামটি বুঝতে চায় তাকে অবশ্যই বুঝতে হবে mainযখন কোডবেজের আরও অস্পষ্ট কোণগুলি প্রায়শই ঘুরে দেখা যেতে পারে।

তবে, পাইথন কোডবেস Py_Mainএই নিয়মটি খেলতে কোডটি বাইরে চাপছে না তবে আপনি mainকোনও লাইব্রেরি থেকে রফতানি করতে পারবেন না বা কোনও ফাংশন হিসাবে কল করতে পারবেন না বলে।


-1

উপরে বেশ কয়েকটি প্রযুক্তিগত উত্তর রয়েছে, এটিকে একপাশে ছেড়ে দিন।

একটি প্রধান সংক্ষিপ্ত হওয়া উচিত কারণ এটি একটি বুটস্ট্র্যাপ হওয়া উচিত। প্রধানটি কয়েকটি সংখ্যক অবজেক্ট ইনস্ট্যান্ট করে তোলে, প্রায়শই একটি যা কাজ করে। অন্য কোথাও যেমন এই জিনিসগুলি ভালভাবে নকশা করা, সংহতকরণ, আলগাভাবে মিলিত, encapsulated, ...

যদিও এক লাইনের মূল কলটিতে অন্য দৈত্য পদ্ধতিতে প্রযুক্তিগত কারণ থাকতে পারে তবে নীতিগতভাবে আপনি সঠিক। একটি সফ্টওয়্যার ইঞ্জিনিয়ারিং দৃষ্টিকোণ থেকে, কিছুই অর্জন করা যায় নি। যদি পছন্দটি একটি দৈত্য পদ্ধতির কলকারী এক লাইনের মধ্যবর্তী হয় এবং প্রধান নিজেই একটি দৈত্য পদ্ধতি হয় তবে পরবর্তীটি ভগ্নাংশটি কম খারাপ হয়।


আপনি ধরে নিচ্ছেন যে "সি ++ কোডে অবজেক্ট এবং কেবলমাত্র অবজেক্ট ব্যবহার করা উচিত"। এটি সত্য নয়, সি ++ একটি বহুমুখী ভাষা এবং কিছু অন্যান্য ভাষার মতো ওও ছাঁচে সবকিছু জোর করে না।
বেন ভয়েগট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.