Кіріспе

Бағдарламалық жасақтаманы жобалау әдісі. Модульдік бағдарламалау – бағдарламаның функционалдығын тәуелсіз, бірін-бірі алмастыратын модульдерге бөлуге баса назар аударатын бағдарламалық жасақтаманы жобалау әдісі. Әр модульде қажетті функционалдықтың бір ғана аспектісін орындау үшін қажеттінің бәрі болады. Модуль интерфейсі модуль ұсынатын және қажет ететін элементтерді көрсетеді. Интерфейсте анықталған элементтер басқа модульдерде көрінеді. Орындау коды интерфейсте жарияланған элементтерге сәйкес келетін жұмыс кодын қамтиды. Модульдік бағдарламалау құрылымдық бағдарламалаумен және объектіге бағытталған бағдарламалаумен тығыз байланысты, олардың барлығы да үлкен бағдарламалар мен жүйелерді кішірек бөліктерге бөлу арқылы құруды жеңілдету мақсатын көздейді және барлығы 1960-шы жылдарға тарта басталады. Бұл терминдердің тарихи қолданылуы тұрақсыз болғанымен, қазіргі уақытта "модульдік бағдарламалау" бүкіл бағдарламаның кодын бөліктерге бөлуді білдіреді: құрылымдық бағдарламалау – құрылымдық басқару ағынының төменгі деңгейлі кодын пайдалану, ал объектіге бағытталған бағдарламалау – объектілердің деректерін пайдалану, дерек құрылымының бір түрі. Объектіге бағытталған бағдарламалауда модульдерді құрастыру үшін архитектуралық үлгі ретінде интерфейстерді пайдалану интерфейске негізделген бағдарламалау деп аталады.

Тарих

Модульдік бағдарламалау, ішкі жүйелер (әсіресе кіріс-шығыс операциялары үшін) және бағдарламалық кітапханалар түрінде, алғашқы бағдарламалық жүйелерге дейін жетеді, онда кодты қайта пайдалану мақсатында қолданылды. Модульдік бағдарламалаудың өзі, модульділік принципіне негізделген, 1960 және 1970 жылдардың соңында құрылымдық бағдарламалау (1960 жылдар) тұжырымдамасының кеңейтілген нұсқасы ретінде дамыды. "Модульдік бағдарламалау" термині кемінде 1968 жылдың шілдесінде Ларри Константиннің Ақпарат және жүйелер институтында ұйымдастырылған Модульдік бағдарламалау жөніндегі ұлттық симпозиумда қолданылды; басқа маңызды түсініктер – ақпаратты жасыру (1972) және қызығушылықтарды бөлу (SoC, 1974). Модульдер ALGOL 68 (1968) тілінің бастапқы спецификациясына енбеді, бірақ алғашқы іске асыруларда, ALGOL 68 R (1970) және ALGOL 68C (1970) тілдерінде кеңейтімдер ретінде қосылды және кейіннен ресми түрде бекітілді. Модульдік бағдарламалауға арналған алғашқы тілдердің бірі – Никлаус Вирттің Modula (1975) тілі болды, ол көп ұзаққысы жоқ. Тағы бір ерте модульдік тіл – Xerox PARC жасаған Mesa (1970-ші жылдар) тілі, ал Вирт Mesa және оның ізінен келген Modula 2 (1978) тілдерін пайдаланды, ол кейінгі тілдерге, әсіресе Modula 3 (1980-ші жылдар) тіліне ықпал етті. Modula тілінде модульден объектіні атау үшін нүктелі жазбаны қолдану (мысалы, M.a, M модулінен a объектісін көрсету үшін), жазбаның өрісіне кіру үшін қолданылатын жазбамен (сондай-ақ объектілердің атрибуттары немесе әдістері үшін) сәйкес келеді және қазір кең таралған, C#, Dart, Go, Java, OCaml және Python тілдерінде де кездеседі. Модульдік бағдарламалау 1980-ші жылдардан бастап кеңінен таралды: бастапқы Pascal тілі (1970) модульдерді қамтымады, бірақ кейінгі нұсқалары, атап айтқанда UCSD Pascal (1978) және Turbo Pascal (1983) оларды "бірліктер" түрінде қосты, сондай-ақ Pascal тіліне негізделген Ada (1980) тілі де оларды қолданды. Extended Pascal ISO 10206:1990 стандарты модульдік қолдау жағынан Modula2 тіліне жақын болды. Standard ML (1984) тілі модульдер арасындағы байланысты жүзеге асыру үшін функторларды (параметрленген модульдерді) қамти отырып, ең толық модульдік жүйелердің біріне ие. 1980 және 1990 жылдары модульдік бағдарламалау объектіге бағытталған бағдарламалаумен көлеңкеленді және оның әсеріне түсті, әсіресе C++ және Java тілдерінің танымалдылығына байланысты. Мысалы, C тілдер отбасы C++ (алғашқыда C with Classes, 1980) және Objective C (1983) тілдерінде объектілер мен сыныптарды қолдады, бірақ модульдерді 30 жыл немесе одан да көп уақыттан кейін ғана қолдады. Java (1995) тілі модульдерді пакеттер түрінде қолдайды, бірақ кодты ұйымдастырудың негізгі бірлігі – сынып. Алайда, Python (1991) тілі бастапқыда модульдер мен объектілерді де кеңінен қолданды, модульдерді кодты ұйымдастырудың негізгі бірлігі ретінде және "пакеттерді" одан да ірі бірлік ретінде пайдаланды; ал Perl 5 (1994) тілі модульдер мен объектілерді де қолдайды, CPAN (1993) репозиторийінен көптеген модульдер қолжетімді. OCaml (1996) тілі ML тілінен модульдер мен функторларды қолдануды қабылдады. Модульдік бағдарламалау қазір кеңінен таралған және 1990 жылдардан бері дамытылған барлық негізгі тілдерде қолданылады. Тілдер арасында модульдердің маңыздылығы әртүрлі, ал сыныптарға негізделген объектіге бағытталған тілдерде ұйымдастыру мен инкапсуляция бірлігі ретінде сыныптармен шатасу мен үйлесімділік әлі де кездеседі, бірақ бұл екеуі де ерекше түсініктер ретінде жақсы қалыптасқан.

Терминология

Модульдің орнына кейде ассемблея (C#, F# немесе Visual Basic NET сияқты NET тілдерінде) немесе пакет (Dart, Go немесе Java сияқты) термині қолданылады. Басқа дамыту орталарында бұл жеке ұғымдар; Python-да пакет – модульдер жиынтығы, ал Java 9-да жаңа модуль тұжырымы (жақсартылған қол жеткізу бақылауымен пакеттер жиынтығы) енгізілді. Сонымен қатар, "пакет" термині бағдарламалық құралдарда басқа да мағыналарда қолданылады (мысалы, .NET NuGet пакеттері). Компонент – ұқсас ұғым, бірақ көбінесе жоғары деңгейде қарастырылады; компонент – бүкіл жүйенің бір бөлігі, ал модуль – жеке бағдарламаның бір бөлігі. "Модуль" терминінің көлемі тілдер арасында едәуір өзгереді; Python-да ол өте шағын, әрбір файл – модуль, ал Java 9-да оның ауқымы үлкендеу болып жоспарланған, онда модуль – пакеттер жиынтығы, ал пакеттер өз кезегінде файлдар жиынтығы болып табылады. Модульдерді атау үшін "бірлік" термині де қолданылады, ол Pascal тілінің диалекттерінде жиі кездеседі.

Тілдік қолдау

Модульдік тұжырымдаманы ресми түрде қолдайтын тілдерге Ada, ALGOL, BlitzMax, C++, C#, Clojure, COBOL, Common Lisp, D, Dart, eC, Erlang, Elixir, Elm, F, F#, Fortran, Go, Haskell, IBM/360 Assembler, Control Language (CL), IBM RPG, Java, Julia, MATLAB, ML, Modula, Modula 2, Modula 3, Morpho, NEWP, Oberon, Oberon 2, Objective C, OCaml, бірнеше Паскаль туындылары (Component Pascal, Object Pascal, Turbo Pascal, UCSD Pascal), Perl, PHP, PL/I, PureBasic, Python, R, Ruby, Rust, JavaScript, Visual Basic (.NET) және WebDNA жатады. Модульдерді қолдамайтын тілдердің айқын мысалдары – C және олардың бастапқы түрінде C++ және Pascal. Дегенмен, C және C++ жеке компиляцияға және декларативтік интерфейстерді анықтауға, бас файлдарды пайдалану арқылы мүмкіндік береді. Objective C-ге модульдер iOS 7 (2013) нұсқасында қосылды; C++-қа C++20 стандартымен, ал Паскальдың орнын бастапқыда модульдерді қамтитын Modula және Oberon тілдері, сондай-ақ модульдерді қамтитын түрлі туындылары басты. JavaScript ECMAScript 2015 жылдан бастап туа біткен модульдерге ие. Модульдік бағдарламалау, тілде аталатын модульдерді қолдау үшін нақты синтаксистік мүмкіндіктер болмаған жағдайда да, мысалы C тілінде жүзеге асырылуы мүмкін. Бұл қолданыстағы тіл мүмкіндіктерін, мысалы, кодтау конвенцияларын, бағдарламалау ережелерін және физикалық код құрылымын пайдалану арқылы іске асырылады. IBM i интеграцияланған тілдік ортада (ILE) бағдарламалау кезінде де модульдерді қолданады.

Негізгі аспектілер

Модульдік бағдарламалауда мәселелер осылай бөлінеді: модульдер логикалық тұрғыдан жеке функцияларды орындайды және жақсы анықталған интерфейстер арқылы өзара әрекеттеседі. Көбінесе модульдер бағытталған ациклдік графты (DAG) құрайды; мұндай жағдайда модульдер арасындағы циклдық тәуелділік олардың біртұтас модуль болуы керектігін көрсетеді. Егер модульдер DAG құраса, оларды иерархиялық түрде құруға болады, онда ең төменгі деңгейдегі модульдер тәуелсіз болады, яғни ешқандай модульге тәуелді емес, ал жоғары деңгейдегі модульдер төменгі деңгейдегілерге тәуелді болады. Нақты бағдарлама немесе кітапхана өзінің иерархиясының жоғарғы деңгейлі модулі болып табылады, бірақ сол сияқты жоғары деңгейдегі бағдарламаның, кітапхананың немесе жүйенің төменгі деңгейлі модулі ретінде де қарастырылуы мүмкін. Модульдік жүйе құрғанда, монолиттік қолданба жасаудың орнына (онда ең кішкентай компонент – бүкіл жүйе), бірнеше кішкентай модульдер жеке жазылады, олар біріктірілгенде орындалатын қолданба бағдарламасын құрайды. Әдетте, олар жеке-жеке компиляцияланады, содан кейін линкер арқылы байланыстырылады. Just-in-time компиляторы осы құрастырудың бір бөлігін орындау кезінде "ұшып" жасай алады. Бұл тәуелсіз функциялар көбінесе бағдарламаны басқару функциялары немесе нақты тапсырма функциялары ретінде жіктеледі. Бағдарламаны басқару функциялары бір бағдарлама үшін жұмыс істеуге арналған. Ал нақты тапсырма функциялары әртүрлі бағдарламаларда қолданылуы үшін дайындалған. Дұрыс құрылған модульдік жүйелер дәстүрлі монолиттік жүйелерге қарағанда әлдеқайда қайта пайдалануға ыңғайлы, себебі осы модульдердің барлығы (немесе көпшілігі) басқа жобаларда өзгеріссіз қайта қолданылуы мүмкін. Бұл жобаларды бірнеше кішкентай жобаларға бөлуге де мүмкіндік береді. Теориялық тұрғыдан алғанда, модульдік бағдарламалық жобаны үлкен командалар оңай құрастыра алады, өйткені команда мүшелері бүкіл жүйені жасамайды және оның толыққанды түрі туралы білуінің қажеті жоқ. Олар тек өздеріне берілген кішкентай тапсырмаға назар аудара алады.