Thursday, March 4, 2021

Design Patterns: Strategy

 


მეგობრებო, განვაგრძობ პროგრამირების სფეროში არსებული თემების მიმოხილვას. ამ კონკრეტულ პოსტში მიმოვიხილავ Behavioral Design Pattern [ქცევითი დიზაინის ნიმუშები] - ის ერთ-ერთ კონკრეტულ ელემენტს, რომელსაც Strategy  [სტრატეგია] ეწოდება. სტრატეგია გვაძლევს საშუალებას დიდი ალგორითმი/ლოგიკა დავყოთ პატარ-პატარა ალგორითმების ოჯახად და runtime-ის დროს გამოვიყენოთ ოჯახის კონკრეტული წევრი, რომელიც გვჭირდება და არ მოვარგოთ ერთი უზარმაზარი ლოგიკა ყველაფერს. მოდით განვიხილოთ ეს ყველაფერი კონკრეტულ მაგალითზე. დავუშვათ გვაქვს ევროკავშირის ქვეყნებში ფულის გადარიცხვის სისტემა  და ბიზნესისგან შემოვიდა Task [დავალება] რომ მომხმარებელს გამოვუთვალოთ და დავუბეჭდოთ თუ რა იქნება გადარიცხვის საკომისიო, ანუ გადასარიცხი თანხის გარდა კიდევ დამატებით რა ღირებულების გადახდა მოუწევს. ვიცით გადასარიცხი თანხა, ქვეყანა, ბანკი და ანგარიშის ნომერი საიდანაც ვრიცხავთ და ასევე ქვეყანა, ბანკი და ანგარიშის ნომერი სადაც ამ თანხას ვრიცხავთ. 


    

როგორც კოდის ფრაგმენტიდან ჩანს, ვქმნით MoneyTransfer კლასის ობიექტს. ამ კლასს აქვს ალგორითმი CalculateTransferFee() რომელიც ითვლის საკომისიოს და შემდგომ შედეგს ვბეჭდავთ კონსოლში:  

კონსოლმა დაგვიბეჭდა, რომ ამ კონკრეტული პარამეტრებით გადარიცხვა ეღირება დამატებით 25 ევრო.

მოდით ჩავიხედოთ კლასის ამ მეთოდში და გავარკვიოთ თუ როგორ არის კოდი ორგანიზებული.



 საკომისიო ითვლება ქვეყნებისა და ბანკების მიხედვით. როგორც კოდიდან ჩანს, ჩვენი სისტემისთვის ამ მომენტში შესაძლებელია მხოლოდ იტალიისა და საფრანგეთის ბანკებში გადარიცხვა, მაგრამ ბიზნესის ცვალებასთან ერთად იზრდება მოთხოვნებიც. ადვილად შესაძლებელია რომ დაემატოს, მაგალითად  ესპანეთი, გერმანია, ბელგია და ა.შ. ეს ყოველივე გამოიწვევს ჩვენი ალგორითმის გაზრდას, რის შედეგადაც, სისტემის runtime-ის დროს თუ მჭირდება მხოლოდ ბელგიაში გადარიცხვა, მომიწევს იმ მეთოდის გამოძახება, რომელშიც აღწერილია ევროკავშირის ყველა ქვეყნის ლოგიკა სადაც სისტემას გადარიცხვა შეუძლია. Strategy პატერნს შეუძლია ეს პრობლემა თავისებურად გადაგვიჭრას: შევქმნათ ITransferStrategy ინტერფეისი, რომელშიც განვსაზღვრავთ CalculateTransferFee კონტრაქტს:


ინტერფეისის შექმნის შემდეგ საჭიროა საკომისიოს გამოთვლის სხვადასხვა იმპლემენტაციები, რადგან გვაქვს სხვადასხვა ქვეყნები. ამისათვის ვიქცებით შემდეგნაირად:  ვქმნით კლასებს და ამ კლასებში ვაიმპლემენტირებთ ჯერ ITrasferStrategy ინტერფეისს  და შემდგომ ინტერფეისში კონტრაქტით აღწერილ მეთოდს.




როგორც ხედავთ შევქმენით ორი კლასი : ItalyTransferStrategy და FranceTransferStrategy რომლებიც ცალ-ცალკე აიმპლემენტირებენ საკომისიოს გადარიცხვის ლოგიკებს. ისღა დაგვრჩენია MoneyTransfer კლასში არსებული ლოგიკა გავამარტივოთ.




შედეგი სახეზეა. ობიექტი, რომელიც ITransferStrategy ინტერფეის აიმპლემენტირებს დავამატეთ როგორც კლასის property : _transferStrategy. MoneyTransfer-ის ობიექტის შექმნის დროს ის შეიძლება იყოს ItalyTransferStrategy ან FranceTransferStrategy. CalculateTransferFee() მეთოდს უწევს მხოლოდ  ინტერფეისში კონტრაქტით აღწერილი  მეთოდის გამოძახება, რომელსაც  გადასცემს საკუთარ თავს. კოდის ორგანიზება საკმაოდ გაუმჯობესდა და CalculateTransferFee მეთოდი განიტვირთა. ეხლა შევხედოთ თუ როგორ ვიყენებთ Main მეთოდში ამ ყოველივეს. 




 

Main-ში უკვე runtime-ის დროს ვარკვევთ რომელი ქვეყანა აირჩია გადასარიცხად, შესაბამისად moneTransfery ობიექტს ვანიჭებთ კონკრეტულ სტრატეგიას property-ს სახით, რათა გამოთვალოს გადარიცხვის საკომისიო. ამით Strategy დიზაინის ნიმუშმა შეასრულა მასზე დაკისრებული ვალდებულება და CalculateFee-ს დიდი ალგორითმი დაყო პატარა ნაწილებად და თუ რომელი ნაწილია საჭირო, მაგას runtime-ის დროს სისტემა თვითონ საზღვრავს.





Friday, December 25, 2020

Overthinking - პრობლემა, რომელიც თრგუნავს ადამიანის ცხოვრებას და ვნებს ჯანმრთელობას



 


Overthinking - ეს ინგლისური ტერმინი უბრალოდ ქართულად, რომ გადავთარგმნოთ ნიშნავს ზედმეტ ფიქრს. ადამიანური ხასიათების, ემოციების, სურვილებისა და გრძნობების გათვალისწინებით  ჩვენი ცხოვრება სავსე არის დასახული მიზნებითა და ყოველდღიური საჭიროებებით, ყოველ ნაბიჯს წინ სდევს ფიქრები და სიტუაციის გაანალიზება - რა შეიძლება მოჰყვეს კონრეტულ ქმედებას ? ღირს თუ არა ამის განხორციელება ? ხშირად ტვინში კონრეტულ შემთხვევას მოჰყვება ყველა შესაძლო შედეგის განხილვა, შემდგომ ამ შედეგების შედეგების განხილვა და ვიღებთ ჩვენს ცნობიერებაში აწყობილ არარეალურ დროის ხაზს, წინასწარ განჭვრეტილი მოვლენების ჯაჭვს ანუ უბრალოდ ზედმეტ ფიქრებს. ტვინს, ასეთ  მდგომარეობაში, არ შეუძლია ეს ფიქრები გარდაქმნას ქმედებებად ან დადებით შედეგებად, რაც ბუნებრივად ჰქმნის სტრესულ განწყობას და იწვევს დეპრესიას. დეპრესიას მივყავართ მავნე ჩვევებამდე და სერიოზულ ჯანმრთელობის პრობლემებამდე.

განვიხილოთ კონკრეტული მაგალითი. დავუშვათ ადამიანი სწავლობს უნივერსიტეტში და ემზადება სემესტრის ფინალური გამოცდისთვის. ეს გამოცდა საკმაოდ მნიშვნელოვანი და  მისთვის მომზადება შრომატევადია. სტუდენტი მის წინაშე  პრობლემაზე იწყებს ფიქრს:

- აუ ძალიან ბევრი მაქვს სასწავლია და რთული მასალაა, შევძლებ კი მომზადებას ?

- რომ ვერ მოვემზადო კარგად მერე რა იქნება ? იქნება ლექტორმა გვიჯიგროს და ადვილი საკითხები შემოიტანოს, ან გამიმართლოს და რასაც ვისწავლი ის შემხვდეს, ან სხვა სტუდენტმა წინა სესიიდან გამოიტანოს მასალა და მეც იგივე შემხვდეს.

- აუ არა, მე ხო ბედი არა მაქვს, უეჭველი ჩავიჭრები. რომ ჩავიჭრები სემესტრი დამემატება და მერე შეიძლება ფულიც კი ვერ გადავიხადო და უნივერსიტეტიდან გამრიცხონ, კარგ სამსახურზე და ჩემთვის საინტერესო ადამიანებთან ურთიერთობაზე ოცნებაც კი დამთავრდება.

დაახლოებით ესეთი აზრები "გენერირდება" ადამიანის ტვინში. მის წინაშე პრობლემაა, უნდა იმეცადინოს და წარმატებით დაამთავროს, მაგრამ ეს კონკრეტული ფიქრები მას არ ასვენებენ. შესაძლო შედეგებიდან ფიქრობს უარესზე, რადგან ირთვება ტვინის თავდაცვითი ფუქნცია. ეს ყველაფერი იწვევს სტრესს და დეპრესიას, რის ფონზეც კონცენტრაციის შენარჩუნება და მუშაობა ძალიან რთულია და არის ალბათობა რომ ის "საშინელი" შედეგები რაც წინასწარმა ფიქრებმა შექმნა რეალობაში ახდეს. ეს არ ეხება მარტო სწავლას ან მუშაობას, ექვივალენტური პრობლემა შეიძლება დაგვიდგეს პირად ცხოვრებაშიც - ოჯახის წევრებთან, მეგობრებთან, შეყვარებულთან ან ახლადგაცნობილ პირთან ურთიერთობაში, ჯანმრთელობის მდგომარეობისა და ფინანსური პრობლემების გამო, სპორტული მოვლენებისადმი ემოციური კავშირისა და სხვა მრავალ სიტუაციაში. ეს ყოველივე იწვევს სტრესს და  თუ ვერ გავუმკლავდით, ისეთ ვერაგ ჯანმრთელობის პრობლემას, როგორიც არის დეპრესია.

როგორ შეიძლება სტრესთან გამკლავება ? არსებობს ფსიქოთერაპიული მეთოდები, ასევე სპეციალური მედიკამენტები, რომლებიც ნერვებს აწყნარებენ, ცვლიან ტვინის ბიო-ქიმიურ პროცესებს და შესაბამისად ნაკლებად იციკლება ადამიანი ზედმეტ ფიქრებზე.  ყველაზე ოპტიმალური მეთოდი ალბათ საკუთარი თავის ხელში აყვანა და რეჟიმში ჩადგომაა - უნდა დაკავდე სასურველი აქტივობებით, რომლის დროსაც ბედნიერების ჰორმონი გამოგეყოფა, ტვინს არ უნდა მისცე მოდუნების საშუალება და idle მდგომარეობაში ყოფნა. ერთ-ერთი ყველაზე რეკომენდირებული საშუალება არის ჯანსაღი კვება და ფიზიკური აქტივობები, რომლის დროსაც კონცენტრირებულიც ხარ და პლუს სხეული არასასურველი ტოქსინებისგან იწმინდება. 


საბოლოო ჯამში, შეგვიძლია დავასკვნათ, რომ ცხოვრებაში რა ამბიციაც გვაქვს,  ამ ამბიციის რეალიზებისათვის და მიზნის  მისაღწევად უნდა გავაკეთოთ მაქსიმუმი და მოვეშვათ არარეალურ და წინასწარ ფიქრებს, დავკავდეთ იმ აქტივობებით რაც გვიყვარს და ბედნიერებას გვანიჭებს, არ მივცეთ ტვინს უფლება ჩაგვითრიოს საშინელებების მორევში. ესეთი მიდგომა პირველ რიგში ადეკვატურობისა და ჯანმრთელობის შენარჩუნებაში, ასევე არასასურველი სამედიცინო ჩარევის თავიდან არიდებაში დაგვეხმარება.

Saturday, October 24, 2020

Design Patterns: Mediator




პროგრამული უზრუნველყოფის შექმნისას, ამოცანის სპეციფიკიდან გამომდინარე ვაწყდებით სხვადასხვა პრობლემებს, რომლის გადასაჭრელად ვეძებთ მაქსიმალურად ოპტიმალურ გზებს, რათა სისტემა იყოს მდგრადი სამომავლო ცვლილებების მიმართ, იყოს მაქსიმალურად ხელმისაწვდომი და იცოდეს გაუთვალისწინებელ შემთხვევებთან გამკლავება რათა არ გამოვიდეს მწყობრიდან და არ დადგეს უსაფრთხოების პრობლემა.  პროგრამული უზრუნველყოფის ინჟინერიაში, არსებობს სხვადასხვა ტიპის სისტემები და ყველას თავისი სასიცოცხლოდ მნიშნველოვანი სქილები გააჩნია, მაგალითად: ბიზნეს სისტემებმა ფეხი უნდა აუწყონ მომხმარებლის საქმიანობის ცვლილებას, ამისათვის საჭიროა შეუფერხებლად იცვლებოდეს მისი ფუნქციონალი, სამედიცინო სისტემებისთვის კრიტიკულია უსაფრთხოება და ა.შ.

მრავალწლიანი  გამოცდილების შემდეგ გამოჩნდა, რომ პრობლემების უმრავლესობა ერთმანეთს ჰგავს და შესაძლებელია ერთი კონკრეტული გადაწყვეტის სხვადასხვა ამოცანაზე ან მოდულზე მორგება, სწორედ ამას ეწოდება "დიზაინის ნიმუში" ( 😁 ) ანუ Design Pattern. არსებობს უამრავი დიზაინის ნიმუში, მაგრამ ყველაზე პოპულარულია GoF დიზაინის ნიმუშები, სადაც გაერთიანებულია  23 ნიმუში. ეს ნიმუშები კლასიფიცირდება 3 ტიპის მიხედვით: Creational[შემოქმედებითი],  Structural[სტრუქტურული] და Behavioral[ქცევითი] ნიმუშები. ამ კონკრეტულ პოსტში მინდა აღვწერო Mediator ნიმუში, რომელიც ქცევითი ტიპის პატერნებს  განეკუთვნება.

როდესაც OOP (Object-Oriented Programming) ის პრინციპებით ვადეველოპერებთ სისტემას, გვიჩნება სხვადასხვა საჭირო კლასები და მისი ობიექტები. მათი ერთმანეთში ქცევითი ურთიერთქმედება ქმნის სისტემის ფუნქციონალს.  ამოცანის სირთულესთან და სიდიდესთან ერთად განისაზღვრება სწორედ კლასებისა და მისი ობიექტების რაოდენობაც, რაც უფრო დიდია Software Requirement-ები და სისტემის მაშტაბურობა, მით უფრო მეტ ერთმანეთზე ფუნქციურად დამოკიდებულ ობიექტებს ვიღებთ, რამაც შეიძლება კოდში საკმაოდ ბევრი ერთმანეთზე დამოკიდებული მოდულები გააჩინოს. ერთი კლასის ლოგიკის ცვლილებამ შეიძლება გამოიწვიოს მასზე დამოკიდებული სხვა კლასების ცვლილება. მედიატორი სწორედ ამ პრობლემის მოგვარების გზაა. მისი იმპლემენტაციით, შეგვიძლია შევზღუდოთ კლასის ობიექტებს შორის პირდაპირი კომუნიკაცია და ვაიძულოთ ისინი მედიატორის დახმარებით ითანამშრომლონ ერთმანეთთან.




მოდი განვიხილოთ კონკრეტული მაგალითი და C#-ის დახმარებით დავიმპლიმენტიროთ მედიატორი:




გვაქვს Footballer კლასი რომელიც იმპლემენტირებას უკეთებს IFootballer ინტერფეისს. მათში მოქცეულია 2 მეთოდი, KickTheBall  და Move, რომლებიც ვირტუალურად ასახავენ მოედანზე ფეხბურთელის საქმიანობას 😁.



Mediator კლასი რომელიც იმპლემენტირებას უკეთებს IMediator ინტერფეისს. როგორც ხედავთ, Mediator კლასი თავისი მეთოდებით ცდილობს Footballer-კლასს შუამავლობა გაუწიოს. მისი დახმარებით ნებისმიერი სხვა კლასი ურთიერთქმედებას შეძლებს  Footballer კლასთან.




Design Patterns: Strategy

  მეგობრებო, განვაგრძობ პროგრამირების სფეროში არსებული თემების მიმოხილვას. ამ კონკრეტულ პოსტში მიმოვიხილავ  Behavioral Design Pattern [ ქცე...