Кіріспе

Хәлсіз бинарлық интерфейс проблемасы немесе FBI – кейбір объектіге бағытталған бағдарламалау тілдерінің компиляторларындағы кемшілік. Негізгі сынып кітапханасындағы ішкі өзгерістер туындап, одан шыққан кітапханалардың немесе бағдарламалардың жұмысын тоқтатуы мүмкін. Бұл – бағдарламалық құралдың тұрақсыздығының мысалы. Бұл мәселе көбінесе нәзік базалық сынып проблемасы немесе FBC деп аталады, бірақ бұл терминнің мағынасы кеңірек.

Себеп

Бұл проблема көптеген таралған объектіге бағытталған (ОО) тілдері үшін компиляторлар қолданатын "қысқа жол" арқасында туындайды, бұл ерекшелік ОО тілдері C және Pascal сияқты бұрынғы, объектіге бағытталмаған құрылымдық бағдарламалау тілдерінен дамыған кезде сақталған. Бұл тілдерде қазіргі түсінікпен нысандар болмаған, бірақ бір жад орында әртүрлі байланысты ақпаратты сақтайтын "жазба" (немесе C тілінде "құрылым") деп аталатын ұқсас конструкция болды. Нақты жазбаның бөліктеріне оның бастапқы орнын анықтап, сол бастапқы нүктеден бөлікке дейінгі арақашықтықты білу арқылы қол жеткізілді. Мысалы, "адам" жазбасында аты, тегі және әкесінің аты болуы мүмкін, ал бағдарламашы әкесінің атын алу үшін thisPerson.middleInitial деп жазады, компилятор мұны a = location(thisPerson) + offset(middleInitial) сияқты түрлендіреді. Қазіргі заманғы процессорлар мұндай қолжетімділік үшін арнайы командаларды қамтиды. Объектіге бағытталған тілдердің компиляторлары жасалғанда, бұрынғы компилятор технологиясының көп бөлігі пайдаланылды және объектілер жазба тұжырымдамасының негізінде құрылды. Бұл тілдерде объектілер бастапқы орны арқылы анықталды, ал олардың "өрістері" деп аталатын ашық деректеріне белгілі арақашықтық арқылы қол жеткізілді. Іс жүзінде, жалғыз өзгеріс – әр сынып үшін өзгермейтін виртуалды әдіс кестесіне сілтеме жасайтын қосымша өрісті жазбаға қосу болды, яғни жазба өзінің деректерін және әдістерін (функцияларын) сипаттайды. Компиляция кезінде деректерге де, кодқа да (виртуалды әдіс кестесі арқылы) қол жеткізу үшін арақашықтықтар қолданылады.

Симптомдары

Бұл үлкен бағдарламаларда кітапханалардан құрастырылғанда проблема тудырады. Егер кітапхана авторы нысан ішіндегі қоғамдық өрістердің мөлшерін немесе орналасуын өзгертсе, офсеттер енді жарамсыз болып, бағдарлама жұмыс істемей қалады. Бұл ФБР мәселесі. Орындалу логикасындағы өзгерістердің проблема тудыруы мүмкін болғанымен, ФБР-дың жасырын жағы – ештеңе іс жүзінде өзгермеген, тек компиляцияланған кітапханада жасырылған нысанның құрылымы ғана өзгерген. Бір нәрсені doSomething-тен doSomethingElse-ке өзгерту мәселе тудыруы мүмкін деп күтуге болады, бірақ бұл жағдайда doSomething-ті өзгертудің қажеті жоқ, мәселе тек бастапқы кодтың жолдарын түсініктілік үшін жылжыту арқылы да тууы мүмкін. Жағдайды одан да нашар ететіні, бағдарламашы компилятор жасаған құрылымды толығымен немесе жартылай бақылай алмайды, бұл мәселені көзден жасырады. Күрделі объектіге бағытталған бағдарламаларда немесе кітапханаларда жоғары деңгейдегі сыныптар ондаған сыныптардан мұрагерлік алуы мүмкін. Осы базалық сыныптардың әрқайсысы жүздеген басқа сыныптарға да мұрагерлікпен берілуі мүмкін. Бұл базалық сыныптар осал, себебі олардың біріне жасалған шағын өзгеріс одан тікелей немесе басқа сынып арқылы мұрагерлік алған кез келген сыныпқа проблема тудыруы мүмкін. Бұл кітапхананың карточка үйі сияқты бір өзгерістен зақымданып, құлауына әкелуі мүмкін. Мұрагерлік ағашы күрделі болса, өзгерістер енгізіліп жатқанда бұл мәселе байқалмауы мүмкін. Шындығында, базалық сыныпты өзгертетін әзірлеуші, әдетте, оны басқалар жасаған қандай сыныптар қолданатынын білмейді.

Тілдер

Қиын екілік интерфейс мәселесінің бір шешімі – мәселенің бар екенін білетін және оны бастапқыда болдырмайтын тілді жасау. Көптеген қолмен жазылған ОО тілдері, ескі тілдерден дамыған тілдерден өзгеше, жүктелу кезінде барлық смещение кестелерін құрастырады. Кітапхана макетіндегі өзгерістер сол кезде "байқалады". Self сияқты басқа ОО тілдері кітапханалардағы нысандарды көшіріп, өзгерту арқылы орындалу кезінде барлық нәрсені құрастырады, сондықтан бұзылуға ұшырауы мүмкін негізгі класы жоқ. Java сияқты кейбір тілдер ФБИ мәселесін тудырмастан қандай өзгерістер жасау қауіпсіз екендігі туралы кеңейтілген құжаттамаға ие. Тағы бір шешім – компиляция кезеңіндегі смещениелер мен басқа ақпаратты тіркелген аралық файлды жазу, ол метадеректер деп аталады. Линкер кітапхана қолданбаға жүктелгенде осы ақпаратты пайдаланып өзін-өзі түзету үшін қолданады. NET сияқты платформалар осылай істейді. Дегенмен, нарық C++ сияқты, шынымен "позицияға тәуелді" және демек ФБИ көрсететін бағдарламалау тілдерін таңдады. Мұндай жағдайларда мәселені шешудің бірнеше жолы бар. Біреуі кітапхана авторына болашақта қосымша функционалдылықты қосу қажет болған жағдайда, бірнеше "құрастырушы" нысандарды енгізу арқылы жүктеме салады (мұны DirectX кітапханасында қолданылатын құрылымдарда көруге болады). Бұл шешім сіз осы макеттерді тауысып қалғанша жақсы жұмыс істейді және олар жадты қажет ететіндіктен, тым көп қосуға ынтаңыз болмайды. Objective C 2.0 инстанция айнымалыларына қол жеткізу үшін қосымша жанама деңгейді пайдаланып, бұзылмайтын инстанция айнымалыларын қамтамасыз етеді. Тағы бір жартылай шешім – кейде "Pimpl" ("Іске асыруға көрсеткіш") деп аталатын Bridge үлгісін пайдалану. Qt фреймворкі мұндай іске асырудың мысалы болып табылады. Әрбір класс тек бір дерек мүшесін анықтайды, ол іске асыру деректерін сақтайтын құрылымға көрсеткіш болып табылады. Көрсеткіштің мөлшері (белгілі бір платформа үшін) өзгеруі екіталай, сондықтан іске асыру деректерін өзгерту публиктік құрылымның мөлшеріне әсер етпейді. Дегенмен, бұл виртуалды әдістерді жоқ классқа енгізу немесе мұрагерлік графигін өзгерту сияқты басқа да бұзушы өзгерістерді болдырмайды.

Тіркегіштер

Басқа бір шешімге еңбекті байланыстырушы қажет. Objective C-нің бастапқы нұсқасында кітапхана форматы бір кітапхананың бірнеше нұсқасын қолдауға мүмкіндік берді және шақырылған кезде дұрыс кітапхананы таңдау үшін белгілі бір мүмкіндіктерді қамтыды. Дегенмен, бұл әрқашан қажет болған жоқ, себебі офсеттер тек өрістер үшін ғана қажет болды, әдістердің офсеттері орындалу кезінде жиналып, FBI-ға (Binary Function Interface) себеп бола алмады. Әдістер өрістерге қарағанда көбірек өзгеріске ұшырайтындықтан, ObjC-де бастапқыда FBI мәселелері аз болды, ал туындаған мәселелер нұсқалау жүйесімен шешілді. Objective C 2.0 "жаңа орындалу ортасын" қосты, ол өрістер үшін де FBI мәселесін шешті. Сонымен қатар, TOM тілінің барлық элементтері үшін орындалу кезінде жиналатын офсеттер қолданылады, бұл FBI-дың пайда болуын болдырмайды. Мүмкіндігінше динамикалық кітапханалардың орнына статикалық кітапханаларды пайдалану – тағы бір шешім, себебі кітапхана қолданба қайта құрастырылмастан және пайдаланылатын офсеттер жаңартылмастан өзгертілмейді. Алайда, статикалық кітапханалардың өзіне тән мәселелері бар, мысалы, үлкен орындалатын файл және кітапхананың жаңа нұсқалары шыққанда оларды "автоматты түрде" пайдалану мүмкін емес.

Сәулет

Бұл тілдерде проблема бірдеңгейлі мұрагерлік принципін қолдану арқылы (өйткені бұл мұрагерлік ағашының күрделілігін азайтады) және виртуалды функциялары бар негізгі сыныптардың орнына интерфейстерді пайдалану арқылы жеңілдетіледі, себебі интерфейстердің өзі кодты қамтымайды, тек интерфейс жариялаған әрбір әдіс сигнатурасы интерфейсті іске асыратын әрбір нысанмен қолдалатынына кепілдік береді.

Тарату әдісі

Егер кітапханалардың бастапқы коды қолжетімді болса, онда барлық мәселе шешіледі. Содан кейін қарапайым қайта компиляция жеткілікті болады.