paint-brush
Ես սիրահարվեցի իմ ծածկագրին, հետո ստիպված էի սպանել այնկողմից@michaelsalim
Նոր պատմություն

Ես սիրահարվեցի իմ ծածկագրին, հետո ստիպված էի սպանել այն

կողմից Michael Salim6m2024/12/13
Read on Terminal Reader

Չափազանց երկար; Կարդալ

Երբեմն լավագույն կոդը ձեր ջնջած կոդը է: Մի սիրեք ձեր կոդը և արեք այն, ինչ լավագույնն է կոդերի բազայի համար: Այս պատմության մեջ ես ջնջեցի կոդերի հարյուրավոր տողեր, որոնք ես պարզապես գրել էի ավելի կարճ և ավելի լավ լուծման օգտին:
featured image - Ես սիրահարվեցի իմ ծածկագրին, հետո ստիպված էի սպանել այն
Michael Salim HackerNoon profile picture


Ես պարզապես ջնջեցի երեկ գրածս հարյուրավոր տող կոդ և դրանք փոխարինեցի նոր կոդով 32 տողով: Սա TheOpenPresenter- ի գործառույթի համար էր, որն օգտագործվում էր ցույց տալու համար, թե արդյոք աուդիո նվագարկվում է:


Շատ հաճախ ես կաշխատեի մի ֆունկցիոնալության վրա, որն իրագործումը բավականին պարզ է թվում: Այս դեպքում ես պարզապես պետք է ցույց տայի այս պատկերակը, երբ աուդիո նվագարկվում է:

Աուդիո նվագարկման ցուցում


Բավականին պարզ: Սրանցից յուրաքանչյուրը մի տեսարան է, որը պարունակում է բազմաթիվ պլագիններ: Յուրաքանչյուր փլագին ունի իր սեփական հատկությունը, ինչպիսին է isPlaying : Մենք կարող ենք միավորել արժեքները պլագինների միջև, և եթե դրոշը ճիշտ է, մենք կարող ենք ցույց տալ պատկերակը:

Լուծում ճարտարապետություն

Հիմնական խնդիրն այն է, թե ինչպես մուտք գործել այս տվյալները: Տեսեք, մենք կարող էինք ուղղակիորեն մուտք գործել տվյալներ: Բայց յուրաքանչյուր փլագին կարող է ունենալ իր սխեման: Թեև որոշ պլագիններ կարող են ունենալ պարզ isPlaying հատկություն, որոշ այլ հավելվածներ կարող են ավելի բարդ բանի կարիք ունենալ՝ ներկայացնելու դրա խաղային կարգավիճակը:


Պարզ, ինչու՞ չթույլատրել հավելվածին գրանցել հետադարձ զանգ/գործառույթ, որը վերադարձնում է վիճակը:


Սա նույն օրինաչափությունն է, որը TheOpenPresenter-ն օգտագործում է իր շատ հավելումների համար: Եվ մինչ մենք դրանում ենք, մենք կարող ենք այն վերացարկել SceneState օբյեկտի մեջ: Այսպիսով, եթե մենք երբևէ որևէ այլ պետության կարիք ունենանք, մենք կարող ենք այն ավելացնել այստեղ: Ահա թե ինչպես այն կարող է նման լինել plugin-ի համար.


 // The pattern we use for plugins serverPluginApi.onPluginDataCreated(pluginName, onPluginDataCreated); serverPluginApi.onPluginDataLoaded(pluginName, onPluginDataLoaded); serverPluginApi.registerRemoteViewWebComponent( pluginName, remoteWebComponentTag, ); // Example of how the new API might look like serverPluginApi.registerSceneState( pluginName, (_, rendererData) => { return { audioIsPlaying: !!rendererData.find((x) => x.isPlaying), } }, );

Սերվերի կառավարում

Ուշադրություն դարձրեք, որ վերը նշված կոդը մշակվում է սերվերում: Դա պայմանավորված է նրանով, որ TheOpenPresenter-ը բաղկացած է 3 առանձին բաղադրիչներից.

  1. Հեռակառավարման վահանակ - որտեղ ցուցադրվում է այս աուդիո ցուցումը

  2. The Renderer - նվագարկում է աուդիո

  3. Սերվեր - միացնում է երկուսը


Իդեալում, մենք պետք է դա կարգավորենք ճակատային մասում (հեռավոր), որպեսզի լրացուցիչ բեռ չավելացնենք սերվերին: Այնուամենայնիվ, այս գործառույթը գրանցելը կարող է խառնաշփոթ լինել: Մեր ճակատային մասը օգտագործում է վեբ բաղադրիչներով բեռնված միկրո-առանցքային ճարտարապետություն:


Ներքևում գտնվող կարմիր տարածքը React շերտ է: Կանաչ տարածքը բեռնվում է վեբ բաղադրիչների միջոցով և կառավարվում է յուրաքանչյուր հավելվածի կողմից:


TheOpenPresenter վահանակ


Ուշադրություն դարձրեք, որ աուդիո պատկերակը գտնվում է կեղևի ձախ կողմում: Ինչպե՞ս ենք ապահովում մեզ անհրաժեշտ գործառույթը shell-ին: Մենք կարող ենք ներառել JS ֆունկցիա վեբ բաղադրիչի փաթեթում, բայց դա երկարաժամկետ հեռանկարում խառնաշփոթ է թվում:


Սերվերում սրա հետ վարվելը կարծես դա անելու ճիշտ միջոց է:

Տվյալների սանտեխնիկա միջոցով

Այդ որոշմամբ՝ ժամանակն է իրականացման: Կան մի քանի անելիքներ.

  1. Ստեղծեք plugin API-ն
  2. Տրամադրեք այս տվյալները ճակատին
  3. Սպառեք և թարմացրեք միջերեսը

Իրականացնելով

Ես ձեզ չեմ ձանձրացնի մանրամասներով, այնպես որ ահա ակնարկ: API-ն այնքան էլ պարզ չէր, քանի որ մեր տվյալները կարող են բավականին շփոթեցնող լինել: Մի խոսքով, տեսարանը կարող է ունենալ բազմաթիվ պլագիններ: Եվ կարող են լինել մի քանի մատուցողներ, որոնցից յուրաքանչյուրը յուրովի է դիտում տեսարանը: Այսպիսով, plugin-ը կարող է ունենալ բազմաթիվ մատուցողներ, որոնք ցույց են տալիս այն տարբեր ձևերով: Բայց մի փոքր տվյալների մանիպուլյացիայով խնդիրը լուծվեց:


UI-ի սպառում և թարմացում

Արժեքը սպառելը պարզ էր: Ես մտածեցի օգտագործել Yjs-ի իրազեկման արձանագրությունը տվյալների տրամադրման համար, քանի որ դրանք իրական ժամանակում են, և շրջանակն արդեն տեղադրված է: Այսպես է պահվում պետությունը։ Այնուամենայնիվ, սերվերից այս տվյալները ներառելը իր խնդիրն է: Այսպիսով, ես որոշեցի փոխարենը օգտագործել GraphQL-ը, այն արձանագրությունը, որը մենք օգտագործում ենք հարթակի մնացած ամեն ինչի համար:


Այսպիսով, մեզ անհրաժեշտ է միայն զանգահարել վերջնակետը, լսել այն GraphQL-ի բաժանորդագրության միջոցով և անհրաժեշտության դեպքում ցույց տալ պատկերակը: Կատարված է:


Այս տվյալները տրամադրելով ճակատին

Բարեբախտաբար, մենք օգտագործում ենք Postgraphile-ը , ինչը բավականին պարզ է դարձնում GraphQL սխեմայի ընդլայնումը: Մենք կարող ենք նաև այն դարձնել բաժանորդագրություն՝ պարզապես ավելացնելով @pgSubscription GraphQL սխեմային: Այնուհետև այն կդիտի թեմա և կթարմացնի արժեքը, երբ մենք զանգահարենք pg_notify այդ թեմայով: Օրինակ՝

 await pgPool.query( `select pg_notify('graphql:sceneState:${id}','{}');`, [], );


Տվյալների մանիպուլյացիան նյարդայնացնող էր, բայց մի փոքր համբերություն, և դա արված է:


Փազլի վերջին մասը կանչում է pg_notify , երբ դա մեզ անհրաժեշտ է:


Դրա համար մենք կարող ենք ունկնդիր ավելացնել վիճակին (Yjs) և զանգահարել ծանուցում, երբ ինչ-որ բան փոխվի.

 state.observeDeep(async () => { // Call pg_notify here });


Միակ բանը, որ մնում է անել, կատարողականի բարելավումն է: Հենց հիմա ֆունկցիան կանչվում է յուրաքանչյուր փոքր փոփոխության համար, այն նաև թարմացվում է ճակատային մասում: Մենք կարող ենք հաշվարկել ստացված վիճակը և համեմատել, արդյոք ինչ-որ բան փոխվում է, նախքան թարմացումը մղելը:

Ավելի լավ լուծում

Այժմ այս լուծումը, անշուշտ, աշխատում է: Բայց ես ատում էի, որ մենք լսում էինք յուրաքանչյուր փոփոխություն: Դա ավելորդ է, և ես վստահ չեմ, թե ինչպես է ներկայացումը մասշտաբի: Ավելի լավ լուծում կա՞:


Այսպիսով, ես մի վայրկյան հետ քաշվեցի և մի միտք ծագեց. Ի՞նչ կասեք, որ գնանք հիմունքներին և օգտագործենք Yjs-ի տվյալները:


Խնդիրն այն էր, որ յուրաքանչյուր փլագին կարող է օգտագործել տարբեր եղանակներ՝ խաղալու կարգավիճակը նշելու համար: Այսպիսով, մեզ անհրաժեշտ էր միջոց՝ իմանալու, թե ինչպես ինքնուրույն հաշվարկել ստացված վիճակը: Բայց ոչ թե թույլ տալ, որ օգտատերը փոխանցի գործառույթը, ինչո՞ւ չպահագրել սեփականություն, որը նրանք կարող են օգտագործել դա նշելու համար:


Վիճակը հաշվարկելու համար գործառույթ փոխանցելու փոխարեն, յուրաքանչյուր փլագին կարող է սահմանել վերապահված վիճակը անմիջապես իրենց առկա տվյալների կողքին՝ __audioIsPlaying նման հատկություններով: Նրանք կարող էին ուղղակիորեն օգտագործել այս արժեքը, կամ նրանք կարող էին այն համաժամանակացնել իրենց գոյություն ունեցող հատկությունների հետ, ինչպիսիք են.


 const onRendererDataLoaded = ( rendererData, ) => { watchYjs( // Watch the isPlaying property (x) => x.isPlaying, () => { // And if it changes, sync the __audioIsPlaying property rendererData.set("__audioIsPlaying", rendererData.get("isPlaying")); }, ); };

Հին ծածկագրի ջնջում

Նոր մեթոդը փայլուն է. Ոչ մի լրացուցիչ լսող, ոչ մի լրացուցիչ API, պարզապես վերապահված պարզ հատկություն:


Արժեքը. Դե ես արդեն գրել եմ առաջին իրականացման 95%-ը 🫣

«Այնքան ամոթ կլինի ջնջել սա, երբ ես այդքան երկար աշխատել եմ դրա վրա: Մնացած ամեն ինչ կատարյալ է, բացի այս մեկ բանից»: -Իմ միտքը


Սա իմ առաջին անգամը չէ։ Ոչ երկրորդ, ոչ երրորդ: Այս անգամ ընդամենը մի քանի ժամ աշխատանք էր։ Որքան ժամանակ է պահանջվում դրա իրականացման համար, այնքան դժվար է այն բաց թողնելը: Բայց եթե մենք չպետք է կցվենք սերվերներին, մենք նույնպես չպետք է կցվենք մեր գրած կոդին:


Ակնհայտ է, որ երկրորդ իրականացումն ավելի լավն է։ Այն ավելի արագ է, ավելի քիչ շարժվող մասեր, ավելի քիչ API մակերես և ավելի քիչ կոդ, որը պետք է պահպանվի: Առաջին իրականացումն ավելացրել է 289 նոր տող, մինչդեռ երկրորդ իրականացումն ավելացրել է ընդամենը 32 նոր տող:


Ի՞նչ դաս պետք է սովորել այդ դեպքում:

Դե, գուցե նախ գտնեք ամենապարզ լուծումը: Բայց երբեմն միայն դրա մասին մտածելով չենք հասնում լավագույն լուծմանը: Եթե դա այդպես է, մի սիրեք ձեր կոդը և մի վախեցեք այն դեն նետել : Եվ միգուցե բլոգային գրառում գրեք, որպեսզի դրանից ինչ-որ բան ստանաք:


Եթե այսքան հեռու եք կարդացել, գուցե ցանկանաք փորձել TheOpenPresenter-ը : Սա բաց կոդով ներկայացման համակարգ է, որը թույլ է տալիս հեռակա կարգով կառավարել ձեր էկրաններից որևէ մեկը:


Ցույց տալ սլայդերի ցուցադրումներ, նվագարկել տեսանյութեր, օգտագործել որպես վահանակ և շատ ավելին: Ծրագիրը դեռ շատ վաղ է մշակվում, ինչպես կարող եք ասել այս գրառումից, բայց այն բավականաչափ կայուն է կանոնավոր օգտագործման համար: Ես անձամբ օգտագործում եմ այն ամեն շաբաթ իմ հանդիպումների համար:


Ցանկացած հարց, հարցրեք: Կամ ազատ զգալ զեկուցել Github ռեպո-ի խնդիրների մասին: