paint-brush
Како да се справите со сложеноста при дизајнирање софтверски системиод страна на@fairday
64,488 читања
64,488 читања

Како да се справите со сложеноста при дизајнирање софтверски системи

од страна на Aleksei23m2024/02/05
Read on Terminal Reader
Read this story w/o Javascript

Премногу долго; Да чита

Комплексноста е непријател! Ајде да научиме како да се справиме со тоа!
featured image - Како да се справите со сложеноста при дизајнирање софтверски системи
Aleksei HackerNoon profile picture

За што се работи?

Секојдневно, секој момент во текот на нашата инженерска кариера, се среќаваме со многу различни проблеми со различна сложеност и ситуации кога треба да донесеме одлука или да ја одложиме поради недостаток на податоци. Секогаш кога градиме нови услуги, градиме инфраструктура или дури формираме развојни процеси, допираме огромен свет на различни предизвици.


Предизвикувачки, а можеби дури и невозможно е да се наведат сите проблеми. Ќе наидете на некои од овие проблеми само ако работите во одредена ниша. Од друга страна, има многу што сите ние мора да ги разбереме како да ги решиме, бидејќи тие се клучни за изградба на ИТ системи. Со голема веројатност ќе ги сретнете во сите проекти.


Во оваа статија ќе ги споделам моите искуства со некои од проблемите со кои се сретнав при креирањето на софтверски програми.

Што е меѓусекторска грижа?

Ако погледнеме во Википедија, ќе ја најдеме следната дефиниција


Во развојот на софтвер ориентиран кон аспекти, вкрстените грижи се аспекти на програмата што влијаат на неколку модули, без можност да бидат инкапсулирани во некој од нив. Овие грижи често не можат чисто да се разложат од остатокот од системот и при дизајнирање и имплементација, и може да резултираат со расејување (дуплирање на кодот), заплеткување (значајни зависности помеѓу системите) или и двете.


Во голема мера опишува што е тоа, но сакам да го проширам и поедноставам малку:

Вкрстена загриженост е концепт или компонента на системот/организацијата што влијае (или „пресекува“) многу други делови.


Најдобрите примери за такви грижи се системската архитектура, логирање, безбедност, управување со трансакции, телеметрија, дизајн на бази на податоци и има многу други. Ние ќе елаборираме за многу од нив подоцна во оваа статија.


На ниво на код, вкрстените проблеми често се имплементираат со користење на техники како што е програмирање ориентирано кон аспекти (AOP) , каде што овие проблеми се модуларизираат во посебни компоненти кои можат да се применат низ целата апликација. Ова ја одржува деловната логика изолирана од овие грижи, правејќи го кодот почитлив и поодржлив.

Класификација на аспекти

Постојат многу можни начини како да се класифицираат аспектите со нивно сегментирање со различни својства како што се опсегот, големината, функционалноста, важноста, целта и други, но во оваа статија, ќе користам едноставна класификација на опсегот. Со ова, сакам да кажам каде е насочен овој специфичен аспект дали е целата организација, одреден систем или специфичен елемент на тој систем.


Значи, ќе ги поделам аспектите на макро и микро .


Под макро аспект мислам главно размислувања што ги следиме за целиот систем како избраната системска архитектура и неговиот дизајн (монолитен, микросервис, сервисно ориентирана архитектура), технолошки куп, организациска структура итн. Макро аспектите се поврзани главно со стратешки и на високо ниво одлуки.


Во меѓувреме, Micro аспектот е многу поблиску до нивото и развојот на кодот. На пример, која рамка се користи за интеракција со базата на податоци, проектната структура на папки и класи, па дури и специфични обрасци за дизајн на објекти.


Иако оваа класификација не е идеална, таа помага да се структурира разбирањето на можните проблеми и важноста и влијанието на решенијата што ги применуваме на нив.


Во оваа статија, мојот примарен фокус ќе биде на макро аспектите.

Макро аспекти

Организациска структура

Кога само што почнав да учам за софтверската архитектура, прочитав многу интересни написи за законот на Конвеј и неговото влијание врз организациската структура. Особено овој . Значи, овој закон го вели тоа


Секоја организација која дизајнира систем (опширно дефиниран) ќе произведе дизајн чија структура е копија на комуникациската структура на организацијата.


Отсекогаш верував дека овој концепт е навистина многу универзален и го претставува Златното правило.


Потоа почнав да го учам пристапот на Ерик Еванс за дизајнирање управувано од домен (DDD) за системи за моделирање. Ерик Еванс ја нагласува важноста на идентификацијата на ограничен контекст. Овој концепт вклучува поделба на комплексен модел на домен на помали, податливи делови, секој со свој ограничен сет на знаење. Овој пристап помага во ефикасна тимска комуникација, бидејќи ја намалува потребата за широко познавање на целиот домен и го минимизира менувањето на контекстот, со што разговорите стануваат поефикасни. Префрлувањето на контекстот е најлошата работа и одзема ресурси досега. Дури и компјутерите се борат со тоа. Иако е малку веројатно да се постигне целосно отсуство на менување контекст, сметам дека тоа е она кон што треба да се стремиме.


Fantasy about keeping in mind a lot of bounded contexts

Враќајќи се на Законот на Конвеј, најдов неколку проблеми со него.


Првото прашање што го сретнав со Законот на Конвеј, кој сугерира дека дизајнот на системот ја отсликува организациската структура, е потенцијалот за формирање сложени и сеопфатни ограничени контексти. Оваа сложеност се јавува кога организациската структура не е усогласена со границите на доменот, што доведува до ограничени контексти кои се во голема мера меѓусебно зависни и оптоварени со информации. Тоа води до често менување контекст за тимот за развој.


Друго прашање е дека организациската терминологија протекува на ниво на код. Кога организационите структури се менуваат, тоа бара модификации на базата на кодови, трошејќи вредни ресурси.


Така, следењето на Inverse Conway Maneuver помага да се изгради системот и организацијата што ја поттикнуваат саканата софтверска архитектура. Сепак, вреди да се каже дека овој пристап нема да функционира многу добро во веќе формираната архитектура и структури бидејќи промените во оваа фаза се пролонгирани, но тој е исклучително добар кај стартапите бидејќи тие брзо воведуваат какви било промени.

Голема топка од кал

Овој модел или „анти-шаблон“ го поттикнува градењето на систем без никаква архитектура. Нема правила, нема граници и нема стратегија како да се контролира неизбежната растечка сложеност. Комплексноста е најстрашниот непријател во патувањето на градењето софтверски системи.


Entertaining illustration made by ChatGPT

За да избегнеме конструирање на таков тип на систем, треба да следиме конкретни правила и ограничувања.

Архитектура на системот

Постојат огромен број дефиниции за софтверска архитектура. Ми се допаѓаат многу од нив бидејќи покриваат различни аспекти од тоа. Меѓутоа, за да можеме да размислуваме за архитектурата, природно треба да формираме некои од нив во нашите умови. И вреди да се забележи дека оваа дефиниција може да еволуира. Така барем засега го имам следниот опис за себе.


Софтверската архитектура се однесува на одлуките и изборите што ги правите секој ден кои влијаат на изградениот систем.


За да донесувате одлуки што треба да ги имате во вашата „торба“ принципи и обрасци за решавање на проблемите што се појавуваат, исто така е од суштинско значење да се наведе дека разбирањето на барањата е клучно за градење на она што му треба на бизнисот. Сепак, понекогаш барањата не се транспарентни, па дури и не се дефинирани, во овој случај, подобро е да почекате да добиете повеќе појаснување или да се потпрете на вашето искуство и да и верувате на вашата интуиција. Но, како и да е, не можете правилно да донесувате одлуки ако немате принципи и модели на кои ќе се потпрете. Тоа е местото каде што доаѓам до дефиницијата за софтверска архитектура стил.


Стилот на софтверска архитектура е збир на принципи и обрасци кои означуваат како да се изгради софтвер.


Постојат многу различни архитектонски стилови фокусирани на различни страни од планираната архитектура, а примената на повеќе од нив одеднаш е нормална ситуација.


На пример, како што се:

  1. Монолитна архитектура

  2. Дизајн управуван од домен

  3. Врз основа на компоненти

  4. Микроуслуги

  5. Цевки и филтри

  6. Управувано од настани

  7. Микрокернелот

  8. Сервисно ориентирани


и така натаму…


Се разбира, тие имаат свои предности и недостатоци, но најважното нешто што го научив е дека архитектурата еволуира постепено додека зависи од вистинските проблеми. Започнувањето со монолитната архитектура е одличен избор за намалување на оперативните комплексности, многу веројатно оваа архитектура ќе одговара на вашите потреби дури и откако ќе ја достигнете фазата на производ-пазар Fit (PMI) при градење на производот. На размер, може да размислите да се движите кон пристап управуван од настани и микросервиси за постигнување независно распоредување, хетерогена технолошка средина и помалку поврзана архитектура (и помалку транспарентна во меѓувреме поради природата на пристапите водени од настани и pub-sub, ако овие се усвоени). Едноставноста и ефикасноста се блиски и имаат големо влијание една врз друга. Обично, комплицираните архитектури влијаат на брзината на развој на новите функции, поддржувајќи и одржувајќи ги постоечките и предизвикувајќи ја природната еволуција на системот.


Сепак, сложените системи често бараат сложена и сеопфатна архитектура, што е неизбежно.


Прилично, ова е многу широка тема и има многу одлични идеи за тоа како да се структурираат и градат системи за природна еволуција. Врз основа на моето искуство, го разработив следниот пристап:

  1. Речиси секогаш започнува со монолитен стил на архитектура, бидејќи ги елиминира повеќето проблеми што се јавуваат поради природата на дистрибуираните системи. Исто така, има смисла да се следи модуларен монолит за да се фокусира на градежни компоненти со јасни граници. Примената на пристап заснован на компоненти може да им помогне да комуницираат едни со други со користење на настани, но имањето директни повици (познато како RPC) ги поедноставува работите на почетокот. Сепак, важно е да се следат зависностите помеѓу компонентите бидејќи ако компонентата А знае многу за компонентата Б, можеби има смисла да се спојат во една.
  2. Кога ќе се приближите до ситуацијата кога треба да го скалирате вашиот развој и систем, би можеле да размислите да ја следите шемата на Stangler за постепено да ги извлекувате компонентите што треба да се распоредат независно или дури и да се намалат со специфични барања.
  3. Сега, ако имате јасна визија за иднината, што е малку неверојатна среќа, би можеле да се одлучите за посакуваната архитектура. Во овој момент, може да одлучите да се придвижите кон архитектурата на микросервисите со примена на пристапи за оркестрација и кореографија, инкорпорирање на CQRS шаблон за операции за пишување и читање во независна скала, или дури и да одлучите да се придржувате до монолитна архитектура доколку одговара на вашите потреби.


Исто така, од витално значење е да се разберат бројките и метриката како DAU (Дневни активни корисници), MAU (месечни активни корисници), RPC (Барање во секунда) и TPC (Трансакција во секунда), бидејќи тоа може да ви помогне да направите избори бидејќи архитектурата за 100 активни корисници и 100 милиони активни корисници се различни.


Како последна забелешка, би рекол дека архитектурата има значително влијание врз успехот на производот. Лошо дизајнираната архитектура за производите е потребна при скалирање, што многу веројатно води до неуспех, бидејќи клиентите нема да чекаат додека го зголемувате системот, тие ќе изберат конкурент, па затоа треба да бидеме понапред од потенцијалното скалирање. Иако признавам дека понекогаш тоа не би можело да биде слаб пристап, идејата е да се има скалабилен, но не веќе скалиран систем. Од друга страна, да имате многу комплициран и веќе намален систем без клиенти или планови да добиете многу од нив, ќе ве чини пари за вашиот бизнис за ништо.

Избор на стек технологија

Изборот на стек технологија е исто така одлука на макро ниво бидејќи влијае на вработувањето, перспективите на природната еволуција на системот, приспособливоста и перформансите на системот.


Ова е списокот на основни размислувања за избор на технолошки оџак:

  • Барања и сложеност на проектот. На пример, едноставна веб-апликација може да се изгради со Blazor рамката ако вашите програмери имаат искуство со неа, но поради недостатокот на зрелост на WebAssembly, изборот на React и Typescript за долгорочен успех може да биде подобра одлука
  • Приспособливост и потреби за изведба. Ако очекувате да добиете голема количина сообраќај, изборот на ASP.NET Core наместо Django може да биде мудар избор поради неговите супериорни перформанси во справувањето со истовремени барања. Сепак, оваа одлука зависи од обемот на сообраќај што го очекувате. Ако треба да управувате со потенцијално милијарди барања со мала латентност, присуството на „Собирање ѓубре“ може да биде предизвик.
  • Вработување, време за развој и трошоци. Во повеќето случаи, тоа се факторите за кои треба да се грижиме. Времето за пазар, трошоците за одржување и стабилноста на вработувањето ги поттикнуваат вашите деловни потреби без пречки.
  • Тимска експертиза и ресурси. Збирот на вештини на вашиот тим за развој е критичен фактор. Генерално е поефективно да се користат технологии со кои вашиот тим веќе е запознаен, освен ако не постои силна причина да се инвестира во учење на нов стек.
  • Зрелост. Силната заедница и богатиот екосистем на библиотеки и алатки може многу да го олеснат процесот на развој. Популарните технологии често имаат подобра поддршка од заедницата, што може да биде непроценливо за решавање на проблемите и за наоѓање ресурси. Така, можете да заштедите ресурси и да се фокусирате главно на производот.
  • Долгорочно одржување и поддршка. Размислете за долгорочната одржливост на технологијата. Технологиите кои се широко прифатени и поддржани се со помала веројатност да станат застарени и генерално да добиваат редовни ажурирања и подобрувања.


Како има повеќе технолошки купови може да влијае на растот на бизнисот?

Од една перспектива, воведувањето на уште еден куп може да го зголеми вашето вработување, но од друга страна, тоа носи дополнителни трошоци за одржување бидејќи треба да ги поддржите двата купа. Значи, како што реков претходно, според моја гледна точка, само дополнителна потреба треба да биде аргумент за инкорпорирање на повеќе технолошки купови.


Но, што е со принципот на избор на најдобра алатка за одреден проблем?

Понекогаш немате друг избор освен да донесете нови алатки за решавање на одреден проблем врз основа на истите размислувања споменати, во такви случаи, има смисла да се избере најдоброто решение.


Создавањето системи без високо спојување со одредена технологија може да биде предизвик. Сепак, корисно е да се стремиме кон состојба во која системот не е цврсто поврзан со технологијата и нема да умре ако утре одредена рамка или алатка стане ранлива или дури и застарена.


Друго важно размислување е поврзано со зависностите од софтвер со отворен код и комерцијален софтвер. Комерцијалниот софтвер ви дава помала флексибилност и можност да се приспособите. Сепак, најопасниот фактор е заклучувањето на продавачот, каде што станувате зависни од производите, цените, условите и патоказот на продавачот. Ова може да биде ризично ако продавачот ја промени насоката, ги зголеми цените или го прекине производот. Софтверот со отворен код го намалува овој ризик, бидејќи еден ентитет не го контролира. Елиминирањето на една точка на неуспех на сите нивоа е клучот за градење сигурни системи за раст.

Единствена точка на неуспех (SPOF)

Единствена точка на неуспех (SPOF) се однесува на кој било дел од системот што, доколку не успее, ќе предизвика целиот систем да престане да функционира. Елиминирањето на SPOF на сите нивоа е од клучно значење за секој систем кој бара висока достапност. Сè, вклучувајќи го знаењето, персоналот, компонентите на системот, давателите на облак и интернет каблите, може да пропадне.


Постојат неколку основни техники кои би можеле да ги примениме за да ги елиминираме поединечните точки на неуспех:

  1. Вишок. Спроведување на вишок за критичните компоненти. Ова значи да имате резервни компоненти кои можат да ги преземат доколку примарната компонента не успее. Вишокот може да се примени низ различни слоеви на системот, вклучувајќи хардвер (сервери, дискови), вмрежување (врски, прекинувачи) и софтвер (бази на податоци, сервери за апликации). Ако хостирате сè во еден Cloud Provider, па дури и имате резервни копии таму, размислете да изградите редовна дополнителна резервна копија во друг за да ги намалите изгубените трошоци во случај на катастрофа.
  2. Центри за податоци. Дистрибуирајте го вашиот систем на повеќе физички локации, како што се центри за податоци или облак региони. Овој пристап го штити вашиот систем од дефекти специфични за локацијата, како што се прекини на струја или природни катастрофи.
  3. Фајловер. Применете пристап за неуспех за сите ваши компоненти (DNS, CDN, Load balancers, Kubernetes, API Gateways и бази на податоци). Бидејќи проблемите може да се појават неочекувано, од клучно значење е да имате резервен план за брзо замена на која било компонента со нејзиниот клон по потреба.
  4. Услуги со висока достапност. Погрижете се вашите услуги да бидат изградени за да бидат хоризонтално скалабилни и високо достапни од самиот почеток, придржувајќи се до следниве принципи:
    • Вежбајте без државјанство на услугата и избегнувајте складирање на кориснички сесии во кешовите во меморијата. Наместо тоа, користете дистрибуиран кеш систем, како што е Redis.
    • Избегнувајте потпирање на хронолошкиот редослед на потрошувачката на пораките кога развивате логика.
    • Минимизирајте ги неуспешните промени за да спречите нарушување на потрошувачите на API. Онаму каде што е можно, одлучете се за промени компатибилни со наназад. Исто така, земете ги предвид трошоците бидејќи понекогаш, спроведувањето на прекини промени може да биде поисплатливо.
    • Вклучете го извршувањето на миграцијата во гасоводот за распоредување.
    • Воспоставете стратегија за справување со истовремени барања.
    • Спроведување на откривање, следење и евиденција на услуги за да се подобри доверливоста и набљудувањето.
    • Развијте ја деловната логика за да бидете немоќни, признавајќи дека неуспесите на мрежата се неизбежни.
  5. Преглед на зависност. Редовно прегледувајте и минимизирајте ги надворешните зависности. Секоја надворешна зависност може да воведе потенцијални SPOF, па затоа е од суштинско значење да се разберат и да се ублажат овие ризици.
  6. Редовно споделување знаење. Никогаш не заборавајте на важноста од ширење на знаењето во вашата организација. Луѓето можат да бидат непредвидливи, а потпирањето на една индивидуа е ризично. Охрабрете ги членовите на тимот да го дигитализираат своето знаење преку документација. Сепак, внимавајте на прекумерното документирање. Користете различни алатки за вештачка интелигенција за да го поедноставите овој процес.

Заклучок

Во оваа статија опфативме неколку клучни макро аспекти и како можеме да се справиме со нивната сложеност.


Ви благодариме што прочитавте! Се гледаме следниот пат!

L O A D I N G
. . . comments & more!

About Author

Aleksei HackerNoon profile picture
Aleksei@fairday
Hey, I am Alex, a dedicated Software Development Engineer with experience in the .NET environment and architecture

ВИСЕТЕ ТАГОВИ

ОВОЈ СТАТИЈА БЕШЕ ПРЕТСТАВЕН ВО...