Išnagrinėkite šešiakampę ir švariąją architektūras, skirtas prižiūrimoms, mastelio keitimui pritaikytoms ir testuojamoms frontend programoms kurti.
Frontend architektūra: šešiakampė ir švarioji architektūra mastelio keitimui pritaikytoms programoms
Frontend programoms tampant vis sudėtingesnėms, gerai apibrėžta architektūra tampa lemiamai svarbi palaikomumui, testuojamumui ir mastelio keitimui. Du populiarūs architektūriniai modeliai, sprendžiantys šias problemas, yra šešiakampė architektūra (taip pat žinoma kaip „Prievadai ir adapteriai“) ir švarioji architektūra. Nors šie principai kilo iš backend pasaulio, jie gali būti efektyviai pritaikyti frontend kūrimui, siekiant sukurti tvirtas ir pritaikomas vartotojo sąsajas.
Kas yra frontend architektūra?
Frontend architektūra apibrėžia skirtingų frontend programos komponentų struktūrą, organizavimą ir sąveiką. Ji suteikia planą, kaip programa yra kuriama, prižiūrima ir plečiama. Gera frontend architektūra skatina:
- Palaikomumas: Lengviau suprasti, modifikuoti ir derinti kodą.
- Testuojamumas: Palengvina modulinių ir integracinių testų rašymą.
- Mastelio keitimas: Leidžia programai susidoroti su didėjančiu sudėtingumu ir vartotojų apkrova.
- Pakartotinis panaudojamumas: Skatina kodo pakartotinį naudojimą skirtingose programos dalyse.
- Lankstumas: Prisitaiko prie kintančių reikalavimų ir naujų technologijų.
Be aiškios architektūros, frontend projektai gali greitai tapti monolitiniais ir sunkiai valdomais, o tai lemia padidėjusias kūrimo išlaidas ir sumažėjusį lankstumą.
Įvadas į šešiakampę architektūrą
Šešiakampė architektūra, kurią pasiūlė Alistair Cockburn, siekia atskirti pagrindinę programos verslo logiką nuo išorinių priklausomybių, tokių kaip duomenų bazės, vartotojo sąsajos karkasai ir trečiųjų šalių API. Tai pasiekiama per „Prievadų ir adapterių“ koncepciją.
Pagrindinės šešiakampės architektūros sąvokos:
- Branduolys (Domenas): Jame yra programos verslo logika ir panaudojimo atvejai. Jis nepriklauso nuo jokių išorinių karkasų ar technologijų.
- Prievadai: Sąsajos, apibrėžiančios, kaip branduolys sąveikauja su išoriniu pasauliu. Jie atspindi branduolio įvesties ir išvesties ribas.
- Adapteriai: Prievadų realizacijos, jungiančios branduolį su konkrečiomis išorinėmis sistemomis. Yra dviejų tipų adapteriai:
- Varantieji adapteriai (Pirminiai adapteriai): Inicijuoja sąveiką su branduoliu. Pavyzdžiai: vartotojo sąsajos komponentai, komandinės eilutės sąsajos ar kitos programos.
- Varomieji adapteriai (Antriniai adapteriai): Juos kviečia branduolys, kad sąveikautų su išorinėmis sistemomis. Pavyzdžiai: duomenų bazės, API ar failų sistemos.
Branduolys nieko nežino apie konkrečius adapterius. Jis su jais sąveikauja tik per prievadus. Šis atskyrimas leidžia lengvai pakeisti skirtingus adapterius, nepaveikiant branduolio logikos. Pavyzdžiui, galite pereiti nuo vieno vartotojo sąsajos karkaso (pvz., „React“) prie kito (pvz., „Vue.js“) tiesiog pakeisdami varantįjį adapterį.
Šešiakampės architektūros privalumai:
- Geresnis testuojamumas: Pagrindinę verslo logiką galima lengvai testuoti izoliuotai, nepasikliaujant išorinėmis priklausomybėmis. Galite naudoti imitacinius (mock) adapterius, kad imituotumėte išorinių sistemų elgseną.
- Didesnis palaikomumas: Išorinių sistemų pakeitimai turi minimalų poveikį branduolio logikai. Tai palengvina programos priežiūrą ir tobulinimą laikui bėgant.
- Didesnis lankstumas: Galite lengvai pritaikyti programą naujoms technologijoms ir reikalavimams, pridėdami arba pakeisdami adapterius.
- Patobulintas pakartotinis panaudojamumas: Pagrindinę verslo logiką galima pakartotinai naudoti skirtinguose kontekstuose, prijungiant ją prie skirtingų adapterių.
Įvadas į švariąją architektūrą
Švarioji architektūra, kurią išpopuliarino Robert C. Martin (Dėdė Bobas), yra dar vienas architektūrinis modelis, pabrėžiantis atsakomybių atskyrimą ir atsiejimą. Ji orientuota į sistemos, nepriklausomos nuo karkasų, duomenų bazių, vartotojo sąsajos ir bet kokių išorinių veiksnių, kūrimą.
Pagrindinės švariosios architektūros sąvokos:
Švarioji architektūra organizuoja programą į koncentrinius sluoksnius, kurių centre yra abstrakčiausias ir pakartotinai panaudojamas kodas, o išoriniuose sluoksniuose – konkretus ir technologijai specifinis kodas.
- Esybės (Entities): Atstovauja pagrindiniams programos verslo objektams ir taisyklėms. Jos nepriklauso nuo jokių išorinių sistemų.
- Panaudojimo atvejai (Use Cases): Apibrėžia programos verslo logiką ir tai, kaip vartotojai sąveikauja su sistema. Jie valdo esybes, kad atliktų konkrečias užduotis.
- Sąsajų adapteriai (Interface Adapters): Konvertuoja duomenis tarp panaudojimo atvejų ir išorinių sistemų. Šis sluoksnis apima prezenterius, valdiklius ir šliuzus (gateways).
- Karkasai ir tvarkyklės (Frameworks and Drivers): Išorinis sluoksnis, kuriame yra vartotojo sąsajos karkasas, duomenų bazė ir kitos išorinės technologijos.
Priklausomybės taisyklė švariojoje architektūroje teigia, kad išoriniai sluoksniai gali priklausyti nuo vidinių sluoksnių, tačiau vidiniai sluoksniai negali priklausyti nuo išorinių sluoksnių. Tai užtikrina, kad pagrindinė verslo logika yra nepriklausoma nuo jokių išorinių karkasų ar technologijų.
Švariosios architektūros privalumai:
- Nepriklausoma nuo karkasų: Architektūra nepasikliauja kokios nors funkcijų gausios programinės įrangos bibliotekos egzistavimu. Tai leidžia naudoti karkasus kaip įrankius, užuot buvus priverstiems talpinti savo sistemą į jų ribotus rėmus.
- Testuojama: Verslo taisykles galima testuoti be vartotojo sąsajos, duomenų bazės, tinklo serverio ar bet kurio kito išorinio elemento.
- Nepriklausoma nuo vartotojo sąsajos: Vartotojo sąsają galima lengvai keisti, nekeičiant likusios sistemos dalies. Tinklo vartotojo sąsaja gali būti pakeista konsolės vartotojo sąsaja, nekeičiant jokių verslo taisyklių.
- Nepriklausoma nuo duomenų bazės: Galite pakeisti „Oracle“ ar „SQL Server“ į „Mongo“, „BigTable“, „CouchDB“ ar ką nors kita. Jūsų verslo taisyklės nėra susietos su duomenų baze.
- Nepriklausoma nuo bet kokio išorinio veiksnio: Tiesą sakant, jūsų verslo taisyklės tiesiog *nieko* nežino apie išorinį pasaulį.
Šešiakampės ir švariosios architektūros taikymas frontend kūrime
Nors šešiakampė ir švarioji architektūros dažnai siejamos su backend kūrimu, jų principai gali būti efektyviai pritaikyti frontend programoms, siekiant pagerinti jų architektūrą ir palaikomumą. Štai kaip:
1. Identifikuokite branduolį (domeną)
Pirmas žingsnis – identifikuoti pagrindinę jūsų frontend programos verslo logiką. Tai apima esybes, panaudojimo atvejus ir verslo taisykles, kurios yra nepriklausomos nuo vartotojo sąsajos karkaso ar bet kokių išorinių API. Pavyzdžiui, el. prekybos programoje branduolys galėtų apimti logiką, skirtą produktams, pirkinių krepšeliams ir užsakymams valdyti.
Pavyzdys: Užduočių valdymo programoje pagrindinį domeną galėtų sudaryti:
- Esybės: Užduotis, Projektas, Vartotojas
- Panaudojimo atvejai: SukurtiUžduotį, AtnaujintiUžduotį, PriskirtiUžduotį, UžbaigtiUžduotį, GautiUžduočiųSąrašą
- Verslo taisyklės: Užduotis privalo turėti pavadinimą, užduotis negali būti priskirta vartotojui, kuris nėra projekto narys.
2. Apibrėžkite prievadus ir adapterius (šešiakampė architektūra) arba sluoksnius (švarioji architektūra)
Toliau apibrėžkite prievadus ir adapterius (šešiakampė architektūra) arba sluoksnius (švarioji architektūra), kurie atskiria branduolį nuo išorinių sistemų. Frontend programoje tai galėtų būti:
- Vartotojo sąsajos komponentai (Varantieji adapteriai / Karkasai ir tvarkyklės): „React“, „Vue.js“, „Angular“ komponentai, sąveikaujantys su vartotoju.
- API klientai (Varomieji adapteriai / Sąsajų adapteriai): Paslaugos, kurios siunčia užklausas į backend API.
- Duomenų saugyklos (Varomieji adapteriai / Sąsajų adapteriai): „Local storage“, „IndexedDB“ ar kiti duomenų saugojimo mechanizmai.
- Būsenos valdymas (Sąsajų adapteriai): „Redux“, „Vuex“ ar kitos būsenos valdymo bibliotekos.
Pavyzdys naudojant šešiakampę architektūrą:
- Branduolys: Užduočių valdymo logika (esybės, panaudojimo atvejai, verslo taisyklės).
- Prievadai:
TaskService(apibrėžia metodus užduotims kurti, atnaujinti ir gauti). - Varantysis adapteris: „React“ komponentai, kurie naudoja
TaskServicesąveikai su branduoliu. - Varomasis adapteris: API klientas, kuris įgyvendina
TaskServiceir siunčia užklausas į backend API.
Pavyzdys naudojant švariąją architektūrą:
- Esybės: Užduotis, Projektas, Vartotojas (gryni „JavaScript“ objektai).
- Panaudojimo atvejai: CreateTaskUseCase, UpdateTaskUseCase (valdo esybes).
- Sąsajų adapteriai:
- Valdikliai: Apdoroja vartotojo įvestį iš vartotojo sąsajos.
- Prezenteriai: Formatuoja duomenis, skirtus rodyti vartotojo sąsajoje.
- Šliuzai: Sąveikauja su API klientu.
- Karkasai ir tvarkyklės: „React“ komponentai, API klientas („axios“, „fetch“).
3. Įgyvendinkite adapterius (šešiakampė architektūra) arba sluoksnius (švarioji architektūra)
Dabar įgyvendinkite adapterius ar sluoksnius, kurie jungia branduolį su išorinėmis sistemomis. Įsitikinkite, kad adapteriai ar sluoksniai yra nepriklausomi nuo branduolio ir kad branduolys su jais sąveikauja tik per prievadus ar sąsajas. Tai leidžia lengvai pakeisti skirtingus adapterius ar sluoksnius, nepaveikiant branduolio logikos.
Pavyzdys (šešiakampė architektūra):
// TaskService prievadas
interface TaskService {
createTask(taskData: TaskData): Promise;
updateTask(taskId: string, taskData: TaskData): Promise;
getTask(taskId: string): Promise;
}
// API kliento adapteris
class ApiTaskService implements TaskService {
async createTask(taskData: TaskData): Promise {
// Siunčiama API užklausa užduočiai sukurti
}
async updateTask(taskId: string, taskData: TaskData): Promise {
// Siunčiama API užklausa užduočiai atnaujinti
}
async getTask(taskId: string): Promise {
// Siunčiama API užklausa užduočiai gauti
}
}
// React komponento adapteris
function TaskList() {
const taskService: TaskService = new ApiTaskService();
const handleCreateTask = async (taskData: TaskData) => {
await taskService.createTask(taskData);
// Atnaujinamas užduočių sąrašas
};
// ...
}
Pavyzdys (švarioji architektūra):
// Esybės
class Task {
constructor(public id: string, public title: string, public description: string) {}
}
// Panaudojimo atvejis
class CreateTaskUseCase {
constructor(private taskGateway: TaskGateway) {}
async execute(title: string, description: string): Promise {
const task = new Task(generateId(), title, description);
await this.taskGateway.create(task);
return task;
}
}
// Sąsajų adapteriai - Šliuzas
interface TaskGateway {
create(task: Task): Promise;
}
class ApiTaskGateway implements TaskGateway {
async create(task: Task): Promise {
// Siunčiama API užklausa užduočiai sukurti
}
}
// Sąsajų adapteriai - Valdiklis
class TaskController {
constructor(private createTaskUseCase: CreateTaskUseCase) {}
async createTask(req: Request, res: Response) {
const { title, description } = req.body;
const task = await this.createTaskUseCase.execute(title, description);
res.json(task);
}
}
// Karkasai ir tvarkyklės - React komponentas
function TaskForm() {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const apiTaskGateway = new ApiTaskGateway();
const createTaskUseCase = new CreateTaskUseCase(apiTaskGateway);
const taskController = new TaskController(createTaskUseCase);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await taskController.createTask({ body: { title, description } } as Request, { json: (data: any) => console.log(data) } as Response);
};
return (
);
}
4. Įgyvendinkite priklausomybių injekciją
Norėdami dar labiau atsieti branduolį nuo išorinių sistemų, naudokite priklausomybių injekciją, kad pateiktumėte adapterius ar sluoksnius branduoliui. Tai leidžia lengvai pakeisti skirtingas adapterių ar sluoksnių implementacijas, nemodifikuojant branduolio kodo.
Pavyzdys:
// Įšvirkščiame TaskService į TaskList komponentą
function TaskList(props: { taskService: TaskService }) {
const { taskService } = props;
const handleCreateTask = async (taskData: TaskData) => {
await taskService.createTask(taskData);
// Atnaujinamas užduočių sąrašas
};
// ...
}
// Naudojimas
const apiTaskService = new ApiTaskService();
5. Rašykite modulinius testus
Vienas iš pagrindinių šešiakampės ir švariosios architektūros privalumų yra geresnis testuojamumas. Galite lengvai rašyti modulinius testus pagrindinei verslo logikai, nepasikliaudami išorinėmis priklausomybėmis. Naudokite imitacinius adapterius ar sluoksnius, kad imituotumėte išorinių sistemų elgseną ir patikrintumėte, ar branduolio logika veikia kaip tikėtasi.
Pavyzdys:
// Imitacinis TaskService
class MockTaskService implements TaskService {
async createTask(taskData: TaskData): Promise {
return Promise.resolve({ id: '1', ...taskData });
}
async updateTask(taskId: string, taskData: TaskData): Promise {
return Promise.resolve({ id: taskId, ...taskData });
}
async getTask(taskId: string): Promise {
return Promise.resolve({ id: taskId, title: 'Test Task', description: 'Test Description' });
}
}
// Modulinis testas
describe('TaskList', () => {
it('turėtų sukurti užduotį', async () => {
const mockTaskService = new MockTaskService();
const taskList = new TaskList({ taskService: mockTaskService });
const taskData = { title: 'New Task', description: 'New Description' };
const newTask = await taskList.handleCreateTask(taskData);
expect(newTask.title).toBe('New Task');
expect(newTask.description).toBe('New Description');
});
});
Praktiniai aspektai ir iššūkiai
Nors šešiakampė ir švarioji architektūros siūlo didelių privalumų, taikant jas frontend kūrime, reikia atsižvelgti ir į kai kuriuos praktinius aspektus bei iššūkius:
- Padidėjęs sudėtingumas: Šios architektūros gali padidinti kodo bazės sudėtingumą, ypač mažoms ar paprastoms programoms.
- Mokymosi kreivė: Kūrėjams gali tekti išmokti naujų koncepcijų ir modelių, kad galėtų efektyviai įgyvendinti šias architektūras.
- Perdėtas projektavimas (Over-engineering): Svarbu vengti perdėto programos projektavimo. Pradėkite nuo paprastos architektūros ir palaipsniui didinkite sudėtingumą pagal poreikį.
- Abstrakcijos balansavimas: Rasti tinkamą abstrakcijos lygį gali būti sudėtinga. Per daug abstrakcijos gali apsunkinti kodo supratimą, o per mažai – sukelti stiprų susiejimą.
- Našumo aspektai: Pernelyg didelis abstrakcijos sluoksnių skaičius gali turėti įtakos našumui. Svarbu profiliuoti programą ir nustatyti bet kokias našumo kliūtis.
Tarptautiniai pavyzdžiai ir pritaikymai
Šešiakampės ir švariosios architektūros principai taikomi frontend kūrimui nepriklausomai nuo geografinės vietos ar kultūrinio konteksto. Tačiau konkretūs įgyvendinimai ir pritaikymai gali skirtis priklausomai nuo projekto reikalavimų ir kūrėjų komandos pageidavimų.
1 pavyzdys: Pasaulinė el. prekybos platforma
Pasaulinė el. prekybos platforma galėtų naudoti šešiakampę architektūrą, kad atskirtų pagrindinę pirkinių krepšelio ir užsakymų valdymo logiką nuo vartotojo sąsajos karkaso ir mokėjimo šliuzų. Branduolys būtų atsakingas už produktų valdymą, kainų skaičiavimą ir užsakymų apdorojimą. Varantieji adapteriai apimtų „React“ komponentus produktų katalogui, pirkinių krepšeliui ir atsiskaitymo puslapiams. Varomieji adapteriai apimtų API klientus skirtingiems mokėjimo šliuzams (pvz., „Stripe“, „PayPal“, „Alipay“) ir siuntimo paslaugų teikėjams (pvz., „FedEx“, „DHL“, „UPS“). Tai leidžia platformai lengvai prisitaikyti prie skirtingų regioninių mokėjimo būdų ir siuntimo galimybių.
2 pavyzdys: Daugiakalbė socialinės žiniasklaidos programa
Daugiakalbė socialinės žiniasklaidos programa galėtų naudoti švariąją architektūrą, kad atskirtų pagrindinę vartotojo autentifikavimo ir turinio valdymo logiką nuo vartotojo sąsajos ir lokalizacijos karkasų. Esybės atstovautų vartotojus, įrašus ir komentarus. Panaudojimo atvejai apibrėžtų, kaip vartotojai kuria, dalijasi ir sąveikauja su turiniu. Sąsajų adapteriai tvarkytų turinio vertimą į skirtingas kalbas ir duomenų formatavimą skirtingiems vartotojo sąsajos komponentams. Tai leidžia programai lengvai palaikyti naujas kalbas ir prisitaikyti prie skirtingų kultūrinių pageidavimų.
Išvada
Šešiakampė ir švarioji architektūros suteikia vertingų principų, kaip kurti prižiūrimas, testuojamas ir mastelio keitimui pritaikytas frontend programas. Atskirdami pagrindinę verslo logiką nuo išorinių priklausomybių, galite sukurti lankstesnę ir pritaikomesnę kodo bazę, kurią laikui bėgant lengviau tobulinti. Nors šios architektūros iš pradžių gali pridėti šiek tiek sudėtingumo, ilgalaikė nauda palaikomumo, testuojamumo ir mastelio keitimo požiūriu paverčia jas verta investicija sudėtingiems frontend projektams. Nepamirškite pradėti nuo paprastos architektūros ir palaipsniui didinti sudėtingumą pagal poreikį, taip pat atidžiai apsvarstykite susijusius praktinius aspektus ir iššūkius.
Taikydami šiuos architektūrinius modelius, frontend kūrėjai gali kurti tvirtesnes ir patikimesnes programas, kurios gali patenkinti kintančius vartotojų poreikius visame pasaulyje.
Papildoma literatūra
- Šešiakampė architektūra: https://alistaircockburn.com/hexagonal-architecture/
- Švarioji architektūra: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html