Saturday, October 15, 2011

Джангогийн дутагдал

Ойрын үед хүмүүс сэм сэмхнээр джангог их хэрэглэдэг болжээ. Би ч гэсэн джанго жил хагас илүү хэрэглэж энэ хугацаанд яагаад энэ фрэймворк нь гайхалтай байсан бэ? гэдгийг зөндөө харлаа үзлээ хэрэглэлээ. Гэхдээ юм болгонд дутагдалтай тал байдаг. Магадгүй би ганцаараа энэ дутагдалтай талтай нь учраад засаж чадахгүй мангартаад яваад байж болох юм. Хэрэв тийм бол энэ постыг уншиж дууссаныхаа дараа сэтгэгдлээр үлдээгээрэй :)

Джанго "Dont Repeat Yourself" зарчмыг баримталдаг. Нэг хийсэн зүйлийг дахиж хийж болохгүй гэдэг санаа. Өөрөөр хэлбэл нэг натурал тоо эрэмбэлдэг функц бичсэн бол тэр нь бүхэл тоонууд дээр бас ажилладаг байх хэрэгтэй. Цаашилбал бүхэл тоонуудаас бутархай тоог эрэмбэлж болно. Эндээс зөвхөн тоо биш бас тэмдэгтүүдийг. Харьцуулж болох бүхнийг эрэмбэлдэг байж болно. Харав уу? бид нар "DRY" зарчмыг баримтлаад хаанаас хаа хүртэл явчихав?

натурал тоо --> бүхэл тоо --> бутархай тоо --> тэмдэгт --> харьцуулж болох бүхнийг (Ө.х жавагийн Comparable интерфэйсийг хэрэгжүүлсэн)

Гайхалтай. Энэ бүхний эцэст супер эрэмбэлэгчтэй боллоо.

Джанго апп гэдэг хэсгүүдээс бүрддэг. Хөгжүүлэгчид нь "Апп" гэдгийг "Reusable App" гэж нэрлэх дуртай. Ингэснээр нөгөө "DRY" зарчмаараа "Reusable" аппуудыг гаргаж авдаг. Мэдээж энэ апп нь "Супер" байх хэрэгтэй.

Харин яаж апп нь "Супер" болоод янз янзын веб сайтуудад дахин дахин хэрэглэгдэх вэ? Жишээ болгож джангогийн "contrib.comments" аппыг авч үзье. Энэ нь баазад байгаа "дурын" мөрөнд сэтгэгдэл бичих боломжоор хангадаг. Ямар ч мэдээнд сэтгэгдэл бичиж, сэтгэгдэлд нь сэтгэгдэл бичиж, хэрэглэгчид нь сэтгэгдэл бичиж, хуудсанд нь сэтгэгдэл бичиж, ер нь бүх юманд болно. Энэ ерөөсөө л супер бүгдийг хийдийм байна.

Энэ сэтгэгдэл бичихэд тусалсан апп маань бидэнд таалагдсангүй гэж бодъё. Энэнд жаахан л хэсэг дутагдаж? сэтгэгдлийг нь ангилж спам, спам бишээр нь ялгая. Уг нь баазад хадгалж байгаа сэтгэгдэл дээрээ ганцхан "is_spam" гэдэг талбар нэмчихвэл яг болчих гээд байдаг.

1-р боломж. Бид өөрсдөө "contrib.comments"-ийг ашигладаг "comments" гэдэг апп бичиж болно. Ингэхдээ "OneToOne" холболт ашиглаад "Comment" болгонд өөр нэг хүснэгтийн мөрийг холбоно. Тэрхүү өөр хүснэгт нь "is_spam" гэсэн талбартай.

2-р боломж. Бид нар "comments" гэдэг джанго аппыг өөрчилж болохгүй. Яагаад гэж үү? Пайтон дээр хэн __builtins__ модулыг өөрчлөөд явах вэ дээ, энэнтэй яг адилхан. Тэгвэл энэ "comments" аппыг хуулж аваад өөрсдийнхөөрөө өөрчлөөд явъя. "Новш гэж энэ жижигхэн талбарыг нэмэхийн тулд бүхэлд нь хуулж авах ч гэж дээ" гэж бодно байх. Бүр муу тохиолдолд бидний ашигласан аппууд дотор "contrib.comments"-ийг хэрэглэдэг апп байг л дээ. Тэгвэл бид нар 2 ижилхэн жаахан ялгаатай "comments" гэдэг апптай болно. Хэн ч энийг хүсэхгүй тэгэхээр тэрийг 2 биш 1 болгоё. "contrib.comments"-ийг Dependency-гээрээ нэхдэг нөгөө апп маань шинэ зүйлд дасан зохицохын тулд бас өөрчилж янзлагдах хэрэг гарна. Өөрчилсөн л болхөгжүүлэгчдийн ярих дуртай Reusability гэдэг нь өнхрөөд яваад өглөө.

Энд 1-р боломжийг "Performance"-ийн үүднээс авч үзвэл бид яагаад ч дэмжиж чадахгүй. Яагаад гэвэл "contrib.comments" нь заавал "contrib.contenttypes"-ийг суулгасан байхыг шаарддаг. Энэ contenttypes апп нь баазад бүхий л моделиудын мэдээллийг хадгалдаг. Ингэснээр "сэтгэгдэл" маань тэр моделийн, ийм түлхүүртэй объекттой холбогдоно гэж хадгалагдана. Дээрээс нь сэтгэгдэл өөр 1 талбартай "Join" хийх хэрэгтэй нь бид нарын тодорхойлсон "is_spam" гэсэн талбартай модель болно. Энэ мангар байдлыг "өгөгдлийн сан" дээр ч гэсэн үздэг, миний санаж байгаагаар "OneToOne" холболтыг арилгаад нэгтгэдэг.

Хэрвээ танд энэнээс илүү санаа байгаа бол сэтгэгдэл дээр үлдээгээрэй.

Тэгэхээр миний харж байгаагаар Джанго асуудалтай. DRY зарчмыг гайхалтай баримталдаг ч Extensible биш юм байна. Ийм асуудлаас яаж зайлсхийх вэ? Ийм асуудалтай тулгаралгүй тойрч яв гэдэг үг байдийм байна лээ.

Энэ байдлыг ингэж засч болно байх. Джангогийн аппууд нь бөөн функцүүдийн цуглуулга байдаг. Энэ байдлыг эвдэж класс хэлбэртэй болгох. 1.3 дээр зарим "generic view" нь класс хэлбэртэй болсон байна лээ, гэхдээ л бүр илүү класс хэлбэртэй болгомоор байгаа юм. Бүр аппыг нь нэг том класс болгох хэрэгтэй.