ഡെവലപ്പർമാർക്ക് പെട്ടെന്ന് നേടാവുന്ന വിജയങ്ങൾ (quick wins) ഇഷ്ടമാണ്. "ഡാർക്ക് മോഡ് ചേർക്കുക" എന്ന് ഒരു ടിക്കറ്റ് വരുമ്പോൾ, ഏറ്റവും എളുപ്പമുള്ള വഴി വ്യക്തമായി തോന്നുന്നു: light.css എഴുതുക, dark.css എഴുതുക, അവ തമ്മിൽ ടോഗിൾ ചെയ്യുക. ഇത് വൃത്തിയുള്ളതായി തോന്നാം. വേഗത്തിൽ പൂർത്തിയാക്കാം. മൂന്ന് ഘടകങ്ങളുള്ള (components) ഒരു ചെറിയ സൈഡ് പ്രോജക്റ്റിന് ഇത് മതിയാകും. എന്നാൽ നിങ്ങളുടെ ആപ്ലിക്കേഷൻ കുറച്ച് മോഡ്യൂളുകൾക്ക് അപ്പുറത്തേക്ക് വളരുമ്പോൾ, ആ രണ്ടാമത്തെ ഫയൽ ഒരു ആസ്തി എന്നതിന് പകരം ഡ്യൂപ്ലിക്കേറ്റ് ആയി സൂക്ഷിക്കേണ്ട ഒരു ബാധ്യതയായി മാറുന്നു.
രണ്ട് ഫയലുകളുടെ കെണി (The Two-File Trap)
ആദ്യ കാഴ്ചയിൽ ഈ ലോജിക് ശരിയാണെന്ന് തോന്നാം. കാര്യങ്ങൾ വേർതിരിച്ചു നിർത്തുക (Separation of concerns), അല്ലേ? ലൈറ്റ് കാര്യങ്ങൾ ഇവിടെ, ഡാർക്ക് കാര്യങ്ങൾ അവിടെ. എഡിറ്ററിൽ നിങ്ങൾ രണ്ട് ബഫറുകൾ തുറക്കുന്നു. ലൈറ്റ് ഫയലിലെ കാർഡ് സ്റ്റൈലുകൾ ഡാർക്ക് ഫയലിലേക്ക് കോപ്പി ചെയ്യുന്നു, #ffffff-ന് പകരം #1a1a1a നൽകുന്നു, ജോലി പൂർത്തിയാക്കുന്നു.
പ്രശ്നം ആദ്യ ആഴ്ചയിലല്ല. പ്രശ്നം ആറാം മാസത്തിലാണ്, ഒരു ഡിസൈനർ പ്രൈമറി ബട്ടണിന് അല്പം വ്യത്യസ്തമായ ബോർഡർ റേഡിയസ് ആവശ്യപ്പെടുമ്പോഴോ, അല്ലെങ്കിൽ പ്രൊഡക്റ്റ് ടീം ചെക്കൗട്ട് ഫോമിൽ പുതിയൊരു വാണിംഗ് സ്റ്റേറ്റ് ആഗ്രഹിക്കുമ്പോഴോ ആണ്. നിങ്ങൾ ലൈറ്റ് സ്റ്റൈൽഷീറ്റ് അപ്ഡേറ്റ് ചെയ്യുന്നു. ഡാർക്ക് സ്റ്റൈൽഷീറ്റ് നിങ്ങൾ ഒന്ന് കണ്ണോടിക്കുന്നു. ഒരുപക്ഷേ ആ മാറ്റം കോപ്പി ചെയ്യാൻ നിങ്ങൾ ഓർക്കും. ഒരുപക്ഷേ മറന്നുപോയേക്കാം. ആ വിടവിലാണ് ഗുണനിലവാരം നഷ്ടപ്പെടുന്നത്. നിങ്ങൾ ഇനി ഒരു ഇന്റർഫേസ് മാത്രമല്ല പരിപാലിക്കുന്നത്. ഒരേ HTML സ്ട്രക്ചർ പങ്കിടുന്ന രണ്ട് സമാന്തര ഇന്റർഫേസുകളാണ് നിങ്ങൾ പരിപാലിക്കുന്നത്.
തീം ഡ്രിഫ്റ്റ് ഒഴിവാക്കാനാവില്ല (Theme Drift Is Inevitable)
ഈ വിടവിന് ഫ്രണ്ട്എൻഡ് ടീമുകൾ തിരിച്ചറിയാൻ തുടങ്ങുന്ന ഒരു പേരുണ്ട്: തീം ഡ്രിഫ്റ്റ് (theme drift). നിങ്ങളുടെ രണ്ട് സ്റ്റൈൽഷീറ്റുകളും വ്യത്യസ്ത വേഗതയിൽ വികസിക്കുമ്പോഴാണ് ഇത് സംഭവിക്കുന്നത്. ഇവിടെ ഒരു പാഡിംഗ് അഡ്ജസ്റ്റ്മെന്റ്, അവിടെ ഒരു ഷാഡോ മാറ്റം. ഡാർക്ക് ഫയൽ അവഗണിക്കപ്പെട്ട സഹോദരനായി മാറുന്നു. അല്ലെങ്കിൽ അതിലും മോശമായി, അത് ഭയത്തിന്റെ ഉറവിടമായി മാറുന്നു. ഡെവലപ്പർമാർ മാറ്റങ്ങൾ വരുത്തുന്നത് ഒഴിവാക്കാൻ തുടങ്ങുന്നു, കാരണം ഒരു തീമിൽ മാറ്റം വരുത്തുക എന്നാൽ മറ്റൊരു ഫയലിൽ തിരഞ്ഞ് ആ ജോലി ഡ്യൂപ്ലിക്കേറ്റ് ചെയ്യുക എന്നാണ് അർത്ഥം.
ഇതിന്റെ മാനസികമായ ഭാരം (cognitive overhead) വേഗത്തിൽ വർദ്ധിക്കുന്നു. നിങ്ങൾക്ക് CSS ഒരിക്കൽ മാത്രം എഴുതണമെന്നായിരുന്നു ആഗ്രഹം. പകരം നിങ്ങൾ അത് രണ്ടുതവണ എഴുതി, ഇപ്പോൾ ഡിസൈൻ സിസ്റ്റം മാറുന്ന ഓരോ തവണയും നിങ്ങൾ ആ കടത്തിന് പലിശ നൽകിക്കൊണ്ടിരിക്കുന്നു. ലൈറ്റ് ഫയലിൽ ആരോ ഒരു ഫ്ലെക്സ് ഗ്യാപ്പ് (flex gap) അപ്ഡേറ്റ് ചെയ്യുകയും അത് ഡാർക്ക് ഫയലിൽ ചെയ്യാൻ മറന്നുപോവുകയും ചെയ്തതുകൊണ്ട് ഡാർക്ക് മോഡിൽ ഐക്കണുകൾ തെറ്റായി വരുന്നു. ഒരു പുതിയ അക്സസിബിലിറ്റി റൂൾ ഒരു ഷീറ്റിൽ മാത്രം വന്നതുകൊണ്ട് ഫോക്കസ് റിംഗുകൾ അപ്രത്യക്ഷമാകുന്നു. UI വെറുതെ തെറ്റായി കാണുക മാത്രമല്ല ചെയ്യുന്നത്, അത് തകരാറിലായതായി അനുഭവപ്പെടാൻ തുടങ്ങുന്നു.
സെമാന്റിക് ടോക്കണുകൾ ഉപയോഗിക്കുക (Use Semantic Tokens)
ഇതിനുള്ള പരിഹാരം മികച്ചൊരു ഡിഫ് ടൂളോ (diff tool) കർശനമായ കോഡ് റിവ്യൂവോ അല്ല. നിറങ്ങളെക്കുറിച്ചുള്ള ചിന്താഗതിയിൽ മാറ്റം വരുത്തുക എന്നതാണ് പരിഹാരം. നിങ്ങളുടെ സ്റ്റൈലുകളെ അവയുടെ രൂപം അനുസരിച്ച് ക്രമീകരിക്കുന്നത് നിർത്തുക, പകരം അവയുടെ ഉദ്ദേശ്യം (purpose) അനുസരിച്ച് ക്രമീകരിക്കാൻ തുടങ്ങുക. ഇവിടെയാണ് സെമാന്റിക് ടോക്കണുകൾ (semantic tokens) പ്രസക്തമാകുന്നത്.
ഒരു കാർഡിന് വെള്ള ബാക്ക്ഗ്രൗണ്ട് നൽകുന്നതിന് പകരം, അതിന് ഒരു 'സർഫസ് ബാക്ക്ഗ്രൗണ്ട്' (surface background) നൽകുക. ടെക്സ്റ്റിനായി ബ്ലാക്ക് അല്ലെങ്കിൽ ഓഫ്-വൈറ്റ് എന്നിവയിൽ നിന്ന് തിരഞ്ഞെടുക്കുന്നതിന് പകരം, ഒരു 'ടെക്സ്റ്റ് കളർ' തിരഞ്ഞെടുക്കുക. ഉപയോക്താവ് ലൈറ്റ് മോഡാണോ ഡാർക്ക് മോഡാണോ ഇഷ്ടപ്പെടുന്നത് എന്ന് കമ്പോണന്റിന് അറിയണമെന്നോ അത് പ്രശ്നമല്ല. അതിന്റെ ജോലിക്ക് അനുയോജ്യമായ ടോക്കൺ അത് ആവശ്യപ്പെടുന്നു.
ഒരു സാധാരണ ബട്ടണിനെക്കുറിച്ച് ചിന്തിക്കുക. രണ്ട് ഫയലുകളുള്ള ലോകത്ത്, .btn എന്നത് ലൈറ്റ് സ്റ്റൈൽഷീറ്റിൽ വെള്ള ബാക്ക്ഗ്രൗണ്ടും ഡാർക്ക് ബോർഡറുമായി നിലനിൽക്കുന്നു. അതിന്റെ ഇരട്ട ഡാർക്ക് സ്റ്റൈൽഷീറ്റിൽ കറുപ്പിനോട് അടുത്ത ബാക്ക്ഗ്രൗണ്ടും ലൈറ്റ് ബോർഡറുമായി നിലനിൽക്കുന്നു. ഒരു ബട്ടണിനായി ഇരട്ടി കോഡ്. ടോക്കണുകൾ ഉപയോഗിക്കുമ്പോൾ, .btn-ന് ഒരു ഡക്ലറേഷൻ മാത്രമേയുള്ളൂ: ബാക്ക്ഗ്രൗണ്ട് var(--color-surface-secondary) ആണ്, ബോർഡർ var(--color-border-default) ആണ്. ഇവയുടെ മൂല്യങ്ങൾ (values) റൂട്ടിൽ (root) ആണ് ഇരിക്കുന്നത്. സൈറ്റ് ലൈറ്റ് മോഡിലാകുമ്പോൾ, --color-surface-secondary എന്നത് #f8f9fa പോലെയായിരിക്കും. ഡാർക്ക് മോഡിൽ, അതേ ടോക്കൺ #2d2d2d ആയി മാറുന്നു. ബട്ടൺ കമ്പോണന്റ് മാറുന്നില്ല, അതിന് താഴെയുള്ള ഡാറ്റ മാത്രം മാറുന്നു.
സ്ട്രക്ചറും ഡാറ്റയും തമ്മിലുള്ള ഈ വ്യത്യാസം സൂക്ഷ്മമാണെങ്കിലും ശക്തമാണ്. നിങ്ങളുടെ കാർഡ് കമ്പോണന്റ് ലേഔട്ട്, സ്പേസിംഗ്, ടൈപ്പോഗ്രാഫി, എലവേഷൻ എന്നിവ ഒരിക്കൽ മാത്രം നിർവചിക്കുന്നു. നിങ്ങളുടെ തീം ലെയർ കളർ പാലറ്റ് നിർവചിക്കുന്നു. CSS കസ്റ്റം പ്രോപ്പർട്ടികൾ (CSS custom properties) നിർമ്മിക്കപ്പെട്ടത് കൃത്യമായി ഈ വേർതിരിവിനായിട്ടാണ്.
ആർക്കിടെക്ചർ എങ്ങനെ മാറുന്നു (How the Architecture Changes)
ഈ സമീപനം നിങ്ങൾ സ്റ്റൈലുകൾ എഴുതുന്ന രീതിയെ അടിസ്ഥാനപരമായി പുനഃക്രമീകരിക്കുന്നു.
പഴയ രീതി സാധാരണയായി ഇപ്രകാരമാണ്:
- പാഡിംഗ്, റേഡിയസ്, ബാക്ക്ഗ്രൗണ്ട്, ടെക്സ്റ്റ് കളർ, ഷാഡോ എന്നിവ നിർവചിക്കുന്ന ഒരു ലൈറ്റ് കാർഡ് സ്റ്റൈൽഷീറ്റ്.
- നിറങ്ങൾ മാറ്റാൻ വേണ്ടി മാത്രം ഒരേ പ്രോപ്പർട്ടികൾ വീണ്ടും നിർവചിക്കുന്ന ഒരു ഡാർക്ക് കാർഡ് സ്റ്റൈൽഷീറ്റ്.
- ഏത് സ്റ്റൈൽഷീറ്റ് ലോഡ് ചെയ്യണം അല്ലെങ്കിൽ ബോഡിയിൽ ഏത് ക്ലാസ് ടോഗിൾ ചെയ്യണം എന്ന് തീരുമാനിക്കുന്ന ഒരു ലോജിക് ലെയർ.
പുതിയ രീതി ഇപ്രകാരമാണ്:
- ലേഔട്ട് നിർവചിക്കുകയും സെമാന്റിക് ടോക്കണുകൾ നൽകുകയും ചെയ്യുന്ന ഒരു കാർഡ് സ്റ്റൈൽഷീറ്റ്.
- ലൈറ്റ് കോൺടെക്സ്റ്റിൽ ആ ടോക്കണുകൾ എന്താണെന്ന് നിർവചിക്കുന്ന ഒരു തീം ഫയൽ.
- ഡാർക്ക് കോൺടെക്സ്റ്റിൽ ആ ടോക്കണുകൾ എന്താണെന്ന് നിർവചിക്കുന്ന ഒരു തീം ഫയൽ, അല്ലെങ്കിൽ ഒരേ ഫയലിലെ ഒരു ബ്ലോക്ക്.
- കമ്പോണന്റ് ലെയറിൽ തൊടാതെ തന്നെ വാല്യൂ ലെയർ മാറ്റുന്ന ഒരു സിംഗിൾ അറ്റ്രിബ്യൂട്ട് സ്വാപ്പ്.
നിങ്ങൾ സെറ്റപ്പ് സ്ഥിരമായി നിലനിർത്തുന്നു. നിങ്ങൾ ഡാറ്റ മാത്രമേ മാറ്റുന്നുള്ളൂ. ഒരു ഡിസൈനർക്ക് മൂന്നാമതൊരു തീം, ഒരുപക്ഷേ ഒരു ഹൈ-കോൺട്രാസ്റ്റ് മോഡോ അല്ലെങ്കിൽ മിഡ്നൈറ്റ് ബ്ലൂ വേരിയന്റോ അവതരിപ്പിക്കണമെന്നുണ്ടെങ്കിൽ, നിങ്ങൾ കാർഡ് വീണ്ടും എഴുതേണ്ടതില്ല. ടോക്കൺ മാപ്പിൽ ഒരു അസൈൻമെന്റ് കൂടി ചേർത്താൽ മതി. കോംപോണന്റ് ലളിതമായി നിലനിൽക്കുന്നു. അതിന് ഇപ്പോഴും ഒരു സർഫസ് കളർ ആവശ്യമാണ്. ഏത് സർഫസ് കളർ ഉപയോഗിക്കണമെന്ന് തീം അതിനോട് പറയുന്നു.
ഡാറ്റാ അറ്റ്രിബ്യൂട്ട് സ്വിച്ച്
ഇംപ്ലിമെന്റേഷൻ ലളിതവും വായിക്കാൻ എളുപ്പമുള്ളതുമായി നിലനിർത്താം. നിങ്ങളുടെ HTML ടാഗിൽ data-theme="dark" പോലുള്ള ഒരു ഡാറ്റാ അറ്റ്രിബ്യൂട്ട് പ്രയോഗിക്കുക, കൂടാതെ നിങ്ങളുടെ ടോക്കൺ നിർവചനങ്ങൾ അതിന് കീഴിൽ സ്കോപ്പ് ചെയ്യുക.
ജാവാസ്ക്രിപ്റ്റ് പ്രവർത്തിക്കുന്നതിന് മുമ്പ് പേജ് ശരിയായി റെൻഡർ ചെയ്യുന്നതിനായി ലൈറ്റ് എക്സ്പീരിയൻസിനായി :root-ൽ നിങ്ങളുടെ ഡിഫോൾട്ടുകൾ സെറ്റ് ചെയ്യുക. തുടർന്ന് [data-theme="dark"]-ന് കീഴിൽ ടോക്കൺ വാല്യൂകൾ ഓവർറൈഡ് ചെയ്യുക. ഒരു ചെറിയ സ്ക്രിപ്റ്റ് ടോഗിൾ ക്ലിക്കിനായി കാത്തിരിക്കുന്നു, അറ്റ്രിബ്യൂട്ട് അപ്ഡേറ്റ് ചെയ്യുന്നു, പേജിലെ ഓരോ കോംപോണന്റും ഉടനടി പ്രതികരിക്കുന്നു. ഓരോ എലമെന്റിലും ക്ലാസുകൾ മാറ്റിക്കൊണ്ടിരിക്കേണ്ടതില്ല. റെൻഡറിംഗിനിടെ മറ്റൊരു സ്റ്റൈൽഷീറ്റ് ഇമ്പോർട്ട് ചെയ്യേണ്ടതില്ല. ബ്രൗസറിൽ വേരിയബിളുകൾ നേരത്തെ തന്നെ മെമ്മറിയിലുണ്ട്; അത് പുതിയ വാല്യൂസുകൾ ഉപയോഗിച്ച് വീണ്ടും പെയിന്റ് ചെയ്യുക മാത്രമാണ് ചെയ്യുന്നത്.
ഇത് നിങ്ങളുടെ കോഡിനെ വളരെ പ്രായോഗികമായി വൃത്തിയായി സൂക്ഷിക്കുന്നു. .card-ന്റെ എല്ലാ ഇൻസ്റ്റൻസുകളും കണ്ടെത്താൻ രണ്ട് ഡയറക്ടറികളിലായി തിരയേണ്ടി വരില്ല. ഒരേ നോഡിൽ അടുക്കിവെച്ചിരിക്കുന്ന പരസ്പരവിരുദ്ധമായ തീം ക്ലാസുകൾ തമ്മിലുള്ള സ്പെസിഫിസിറ്റി യുദ്ധങ്ങളെക്കുറിച്ച് നിങ്ങൾ ആശങ്കപ്പെടേണ്ടതില്ല. നിങ്ങളുടെ HTML വായിക്കാൻ എളുപ്പമായിരിക്കും. നിങ്ങളുടെ CSS സെൻട്രലൈസ്ഡ് ആയതും സെർച്ച് ചെയ്യാൻ എളുപ്പമുള്ളതുമായിരിക്കും.
ഇത് വാല്യൂസിനെക്കുറിച്ചാണ്, വേർഷനുകളെക്കുറിച്ചല്ല
ഡാർക്ക് മോഡ് എന്നത് വാല്യൂസിനെക്കുറിച്ചാണ്. അത് നിങ്ങളുടെ UI-യുടെ രണ്ടാമതൊരു വേർഷനല്ല. രാത്രിയിൽ നിങ്ങളുടെ കാർഡിന്റെ കോണുകൾ കൂടുതൽ ഉരുണ്ടതാകുന്നില്ല. നിങ്ങളുടെ ഗ്രിഡ് മറ്റൊരു രൂപത്തിലേക്ക് മാറുന്നില്ല. നിങ്ങളുടെ ടൈപ്പ് സ്കെയിലിന് പുതിയ താളം ആവശ്യമില്ല. നിറങ്ങൾ മാറുന്നു, ചിലപ്പോൾ ഷാഡോകൾ അല്പം കൂടി ആഴമുള്ളതാകുന്നു. ഡാർക്ക് മോഡിനെ ഒരു പൂർണ്ണമായ 'റീസ്കിൻ' (reskin) ആയി കാണുന്നത് മെയിന്റനൻസ് ബുദ്ധിമുട്ടുകൾ ഉണ്ടാക്കുന്ന ഓവർ-എഞ്ചിനീയറിംഗാണ്.
ഇത് ശരിയായി ചെയ്യുന്ന ടീമുകൾ അവരുടെ ഡിസൈൻ സിസ്റ്റത്തെ ഒരു ഡാറ്റാബേസ് പോലെയാണ് കാണുന്നത്. കോംപോണന്റുകൾ പേര് ഉപയോഗിച്ച് പ്രോപ്പർട്ടികൾക്കായി ക്വറി ചെയ്യുന്നു. തീമുകൾ റെക്കോർഡുകൾ നൽകുന്നു. ലൈറ്റിൽ നിന്ന് ഡാർക്കിലേക്കുള്ള മാറ്റം ഒരു ക്വറി പാരാമീറ്റർ മാറ്റം മാത്രമാണ്, അല്ലാതെ ഒരു സ്കീമ റീറൈറ്റ് അല്ല.
ആ ചിന്താഗതിയാണ് നിങ്ങളെ തീം ഡ്രിഫ്റ്റിൽ (theme drift) നിന്ന് രക്ഷിക്കുന്നത്. ഒരു കാർഡ്. ഒരു ബട്ടൺ. സ്പേസിംഗിനും സൈസിംഗിനും ഒരൊറ്റ സോഴ്സ് ഓഫ് ട്രൂത്ത്. പാലറ്റ് ഒരിടത്ത് തന്നെ നിലനിൽക്കുന്നു, ലോജിക്കലായി മാപ്പ് ചെയ്യപ്പെട്ടത്, ഉപയോക്താവ് ഇഷ്ടപ്പെടുന്ന ഏത് സാഹചര്യത്തിനും തയ്യാറാണ്.
യഥാർത്ഥ പാഠം
ലൈറ്റിനും ഡാർക്കിനും വേണ്ടി നിങ്ങൾ രണ്ട് CSS ഫയലുകൾ സൂക്ഷിക്കുന്നുണ്ടെങ്കിൽ, നിങ്ങൾ തീമിംഗ് അല്ല ചെയ്യുന്നത്, പകരം ക്ലോണിംഗ് ആണ് ചെയ്യുന്നത്. സെമാന്റിക് ടോക്കണുകളിലേക്ക് മാറൂ, അവയെ ഒരു റൂട്ട്-ലെവൽ ഡാറ്റാ അറ്റ്രിബ്യൂട്ട് ഉപയോഗിച്ച് സ്കോപ്പ് ചെയ്യൂ, കോംപോണന്റുകൾക്ക് അവയുടെ രൂപം ഹാർഡ്കോഡ് ചെയ്യുന്നതിന് പകരം അവയുടെ റോളുകൾക്കായി ആവശ്യപ്പെടാൻ അനുവദിക്കൂ. ആദ്യഘട്ടത്തിലെ റീഫാക്ടറിംഗിന് പ്രയത്നം ആവശ്യമാണ്, എന്നാൽ ഇതിന് പകരമായി ചെയ്യുന്നത് സമാന്തരമായ സ്റ്റൈൽഷീറ്റുകൾക്കിടയിൽ അവസാനമില്ലാത്ത ഒരു പോരാട്ടം തന്നെയായിരിക്കും. ഒരേ കാർഡ് രണ്ടുതവണ എഴുതാൻ ജീവിതം വളരെ ചെറുതാണ്.
