Hierarchical decomposition
Hindi mo dapat simulan kaagad ang pagsusulat ng mga klase para sa iyong aplikasyon. Una kailangan itong idisenyo. Ang disenyo ay dapat magtapos sa isang maalalahanin na arkitektura. At upang makuha ang arkitektura na ito, kailangan mong patuloy na mabulok ang system.
Ang decomposition ay dapat isagawa sa hierarchically - una, ang system ay nahahati sa malalaking functional modules / subsystems na naglalarawan sa operasyon nito sa pinaka-pangkalahatang anyo. Pagkatapos ang mga resultang module ay sinusuri nang mas detalyado at nahahati sa mga submodules o mga bagay.
Bago pumili ng mga bagay, hatiin ang system sa mga pangunahing bloke ng semantiko, hindi bababa sa mental. Sa mga maliliit na aplikasyon, ito ay kadalasang napakadaling gawin: ang isang pares ng mga antas ng hierarchy ay sapat na, dahil ang system ay unang nahahati sa mga subsystem / pakete, at ang mga pakete ay nahahati sa mga klase.
![Hierarchical decomposition](https://cdn.codegym.cc/images/article/d5e9aa2b-5783-430f-b5b5-1832bc33c540/800.jpeg)
Ang ideyang ito ay hindi kasing-liit ng tila. Halimbawa, ano ang kakanyahan ng isang karaniwang "pattern ng arkitektura" bilang Model-View-Controller (MVC)?
Ang lahat ay tungkol sa paghihiwalay ng presentasyon mula sa lohika ng negosyo . Una, ang anumang application ng user ay nahahati sa dalawang module - ang isa ay responsable para sa pagpapatupad ng business logic mismo (Model), at ang pangalawa ay responsable para sa pakikipag-ugnayan sa user (User Interface o View).
Pagkatapos ay lumalabas na ang mga module ay dapat kahit papaano ay nakikipag-ugnayan, para dito nagdagdag sila ng isang Controller, na ang gawain ay upang pamahalaan ang pakikipag-ugnayan ng mga module. Gayundin sa mobile (classic) na bersyon ng MVC, ang Observer pattern ay idinagdag dito upang ang View ay makatanggap ng mga kaganapan mula sa modelo at baguhin ang ipinapakitang data sa real time.
Ang mga karaniwang top-level na module, na nakuha bilang resulta ng unang dibisyon ng system sa pinakamalaking bahagi, ay tiyak:
- Lohika ng negosyo;
- User interface;
- Database;
- Sistema ng pagmemensahe;
- Lalagyan ng bagay.
Karaniwang hinahati ng unang hati ang buong aplikasyon sa 2-7 (maximum na 10 bahagi). Kung hahati-hatiin natin ito sa higit pang mga bahagi, magkakaroon ng pagnanais na ipangkat ang mga ito, at muli tayong makakakuha ng 2-7 top-level na mga module.
Functional na agnas
Ang paghahati sa mga module / subsystem ay pinakamahusay na ginawa batay sa mga gawain na nalulutas ng system . Ang pangunahing gawain ay nahahati sa mga nasasakupan nitong mga subtask, na maaaring lutasin/isagawa nang nakapag-iisa, nang hiwalay sa isa't isa.
Ang bawat module ay dapat na responsable para sa paglutas ng ilang subtask at gawin ang kaukulang function nito . Bilang karagdagan sa functional na layunin, ang module ay nailalarawan din sa pamamagitan ng isang set ng data na kinakailangan para maisagawa nito ang function nito, iyon ay:
Module = Function + Data na kailangan upang maisagawa ito.
Kung ang agnas sa mga module ay tapos na nang tama, ang pakikipag-ugnayan sa iba pang mga module (responsable para sa iba pang mga function) ay magiging minimal. Maaaring ito ay, ngunit ang kawalan nito ay hindi dapat maging kritikal para sa iyong modyul.
Ang isang module ay hindi isang arbitrary na piraso ng code, ngunit isang hiwalay na functionally meaningful at kumpletong unit ng program (subprogram) na nagbibigay ng solusyon sa isang partikular na gawain at, sa isip, ay maaaring gumana nang nakapag-iisa o sa ibang kapaligiran at magagamit muli. Ang module ay dapat na isang uri ng "integridad na may kakayahang relatibong kalayaan sa pag-uugali at pag-unlad." (Christopher Alexander)
Kaya, ang karampatang agnas ay batay, una sa lahat, sa pagsusuri ng mga function ng system at ang data na kinakailangan upang maisagawa ang mga function na ito. Ang mga pag-andar sa kasong ito ay hindi mga pag-andar ng klase at mga module, dahil hindi sila mga bagay. Kung mayroon ka lamang ng ilang mga klase sa isang module, nalampasan mo ito.
Malakas at mahina ang koneksyon
Napakahalaga na huwag lumampas sa modularization. Kung bibigyan mo ang isang baguhan ng monolithic Spring application at hilingin sa kanya na hatiin ito sa mga module, pagkatapos ay ilalabas niya ang bawat Spring Bean sa isang hiwalay na module at isaalang-alang na ang kanyang trabaho ay tapos na. Pero hindi pala.
Ang pangunahing criterion para sa kalidad ng decomposition ay kung paano nakatutok ang mga module sa paglutas ng kanilang mga gawain at independyente.
Ito ay kadalasang binabalangkas tulad ng sumusunod: "Ang mga module na nakuha bilang resulta ng agnas ay dapat na maximally conjugated sa loob (mataas na panloob na pagkakaisa) at minimally interconnected sa bawat isa (mababang panlabas na pagkabit)."
Ang High Cohesion, mataas na cohesion o "cohesion" sa loob ng module, ay nagpapahiwatig na ang module ay nakatuon sa paglutas ng isang makitid na problema, at hindi nakikibahagi sa pagsasagawa ng magkakaibang mga function o hindi nauugnay na mga responsibilidad.
Ang pagkakaisa ay tumutukoy sa antas ng pagkakaugnay ng mga gawaing ginagampanan ng modyul sa isa't isa.
Ang kahihinatnan ng High Cohesion ay ang Single Responsibility Principle - ang una sa limang SOLID na prinsipyo , ayon sa kung saan ang anumang bagay / module ay dapat magkaroon lamang ng isang responsibilidad at hindi dapat magkaroon ng higit sa isang dahilan para sa pagbabago nito.
Low Coupling , maluwag na coupling, ay nangangahulugan na ang mga module kung saan nahahati ang system ay dapat, kung maaari, independyente o maluwag na pinagsama sa isa't isa. Dapat silang makipag-ugnayan, ngunit sa parehong oras alam ang kaunti hangga't maaari tungkol sa isa't isa.
Ang bawat modyul ay hindi kailangang malaman kung paano gumagana ang iba pang modyul, sa anong wika ito nakasulat, at kung paano ito gumagana. Kadalasan, upang ayusin ang pakikipag-ugnayan ng naturang mga module, ginagamit ang isang tiyak na lalagyan, kung saan na-load ang mga module na ito.
Sa wastong disenyo, kung babaguhin mo ang isang module, hindi mo na kailangang mag-edit ng iba, o magiging minimal ang mga pagbabagong ito. Kung mas maluwag ang pagkakabit, mas madaling isulat/maunawaan/palawakin/ayusin ang programa.
Ito ay pinaniniwalaan na ang mahusay na disenyo ng mga module ay dapat magkaroon ng mga sumusunod na katangian:
- Functional na integridad at pagkakumpleto - bawat module ay nagpapatupad ng isang function, ngunit ipinapatupad ito ng maayos at ganap, ang module ay nakapag-iisa na gumaganap ng isang buong hanay ng mga operasyon upang ipatupad ang function nito.
- Isang input at isang output - sa input, ang module ng programa ay tumatanggap ng isang tiyak na hanay ng paunang data, nagsasagawa ng makabuluhang pagproseso at nagbabalik ng isang hanay ng data ng resulta, iyon ay, ang karaniwang prinsipyo ng IPO ay ipinatupad - input -\u003e proseso -\u003e output.
- Lohikal na kalayaan - ang resulta ng gawain ng module ng programa ay nakasalalay lamang sa paunang data, ngunit hindi nakasalalay sa gawain ng iba pang mga module.
- Mahina ang mga link ng impormasyon sa iba pang mga module - ang pagpapalitan ng impormasyon sa pagitan ng mga module ay dapat mabawasan kung maaari.
Napakahirap para sa isang baguhan na maunawaan kung paano bawasan ang pagkakakonekta ng mga module nang higit pa. Bahagyang ang kaalamang ito ay may karanasan, bahagyang - pagkatapos magbasa ng mga matalinong aklat. Ngunit ito ay pinakamahusay na pag-aralan ang mga arkitektura ng mga umiiral na application.
Komposisyon sa halip na mana
Ang karampatang decomposition ay isang uri ng sining at isang mahirap na gawain para sa karamihan ng mga programmer. Ang pagiging simple ay mapanlinlang dito, at ang mga pagkakamali ay magastos.
![](https://cdn.codegym.cc/images/article/d7e785ed-e16d-4354-883c-0ad83327512a/512.jpeg)
Ito ay nangyayari na ang mga nakatuong module ay malakas na pinagsama sa isa't isa at hindi sila maaaring mabuo nang nakapag-iisa. O hindi malinaw kung ano ang tungkulin ng bawat isa sa kanila na may pananagutan. Kung nakatagpo ka ng isang katulad na problema, malamang na ang paghati sa mga module ay ginawa nang hindi tama.
Dapat palaging malinaw kung ano ang papel na ginagampanan ng bawat module . Ang pinaka-maaasahang criterion na ang agnas ay nagawa nang tama ay kung ang mga module ay independiyente at mahalagang mga subroutine na maaaring gamitin sa paghihiwalay mula sa natitirang bahagi ng application (at samakatuwid ay maaaring magamit muli).
Kapag nabubulok ang isang sistema, kanais-nais na suriin ang kalidad nito sa pamamagitan ng pagtatanong sa iyong sarili ng mga tanong: "Anong gawain ang ginagawa ng bawat module?", "Gaano kadaling subukan ang mga module?", "Posible bang gamitin ang mga module nang mag-isa. o sa ibang kapaligiran?" makakaapekto sa iba?"
Kailangan mong subukang panatilihing autonomous ang mga module hangga't maaari . Gaya ng nabanggit kanina, ito ay isang pangunahing parameter para sa wastong agnas . Samakatuwid, dapat itong isagawa sa paraang ang mga module sa una ay mahinang umaasa sa isa't isa. Kung nagtagumpay ka, kung gayon ikaw ay mahusay.
Kung hindi, hindi rin mawawala ang lahat dito. Mayroong ilang mga espesyal na diskarte at pattern na nagbibigay-daan sa iyo upang higit pang mabawasan at pahinain ang mga link sa pagitan ng mga subsystem. Halimbawa, sa kaso ng MVC, ginamit ang pattern ng Observer para sa layuning ito, ngunit posible ang iba pang mga solusyon.
Masasabing ang mga diskarte para sa decoupling ay bumubuo sa pangunahing "toolkit ng arkitekto". Kinakailangan lamang na maunawaan na pinag-uusapan natin ang lahat ng mga subsystem at kinakailangan na pahinain ang koneksyon sa lahat ng antas ng hierarchy , iyon ay, hindi lamang sa pagitan ng mga klase, kundi pati na rin sa pagitan ng mga module sa bawat hierarchical na antas.