Saturday, September 8, 2018

Composite Pattern

Design Pattern-ები არის ერთ-ერთი ყველაზე პოპულარული თემა ბლოგებზე და ასევე ინტერვიუების დროს. ამ პოსტში განვიხილავთ Composite Pattern-ს ერთ-ერთ მაგალითზე. ერთადერთი რაც უნდა დავიმახსოვროთ არის ის, რომ Composite Pattern-ი გამოიყენება რეკურსიული მოქმედების განსახორციელებლად ხისებურ სტრუქტურაზე.


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

ამის შემდეგ გვჭირდება Building, Floor და Room კლასები შესაბამისად, რომელებიც თითოეული იმპლემენტაციას გაუკეთებს Component ინტერფეისს.

  • Building-ში შუქი ჩართულად/გამორთულად ითვლება თუ მის ყველა სართულზე არის ჩართული/გამორთული.
  • Floor-ზე შუქი ჩართულად/გამორთულად ითვლება თუ მის ყველა ოთახში არის ჩართული/გამორთული.
  • Room-ში შუქი ჩართულად/გამორთულად ითვლება თუ შიგნით არის ჩართული/გამორთული.



Building ახორციელებს მისი ყველა სართულისთვის შუქის ჩართვის/გამორთვის ოპერაციას, ხოლო Floor შესაბამისად ახორციელებს იმავე ოპერაციას თავისი ყველა ოთახისთვის.

საბოლოო ეფექტი ის არის, რომ ძირითად ოპერაციას იწყებს Building, რომელიც რეკურსიულად ხორციელდება მის ქვემოთ არსებულ ობიექტებზე (Floor და Room). "დომინოს ეფექტი" არის ერთ-ერთი თვისება Composite Pattern-თვის.

აქვე აღვნიშნოთ რომ default-ად ყველა ოთახში შუქი გამორთულია. ახლა ვნახოთ ტესტ კლასი და შევამოწმოთ რომ ჩვენი სტრუქტურა სწორად მუშაობს.


Tuesday, May 1, 2018

Java 8 HashMaps, Keys და Comparable Interface

Java 8-ში წინა ვერსიებთან შედარებით ბევრი რამ გაუმჯობესებულია. ბევრი კლასი და-update-და. მათ შორის გამონაკლისი არ ყოფილა HashMap, რომელიც ერთ-ერთი ყველაზე ფართოდ გამოყენებადია. ამ პოსტში გავამახვილებ ყურადღებას იმაზე, თუ რა ხდება როცა Hash კოლიზიას აქვს ადგილი.

უპირველეს ყოვლისა, რომელი არის ყველაზე მარტივი გზა იმისა, რომ მოვახდინოთ კოლიზია HashMap-ში ? შევქმნათ კლასი, რომელსაც ექნება თავისი hash ფუნქცია და დავწეროთ მისი ყველაზე ცუდი იმპლემენტაცია (hashCode მეთოდის). ამის ერთ-ერთი მაგალითია ის, რომ hashCode() მეთოდმა ყოველთვის დააბრუნოს რაიმე კონსტანტა. როგორ ფიქრობთ რა მოხდება ამ დროს ? ტექნიკურ ინტერვიებზე ამ კითხვაზე ხშირად პასუხობენ, რომ ყოველი ახალი ჩამატებული ელემენტი HashMap-ში შეცვლის ძველს, რაც სიმართლეს არ შეესაბამება. Hash Collision არ გულისხმობს იმას, რომ HashMap-ში მონაცემები ერთმანეთს გადაეწერება, ეს ხდება მაშინ და მხოლოდ მაშინ როცა ისეთი ორი ელემენტის ჩასმას ვცდილობთ HashMap-ში, რომელთა Key-ები ტოლია equals() მეთოდზე დაყრდნობით, ანუ equals() მეთოდი აბრუნებს true-ს. ელემენტები არა ტოლი გასაღებებით და ერთნაირი hashCode-ებით მოთავსდება ერთსა და იმავე bucket-ში რომელიღაც ტიპის მონაცემთა სტრუქტურაში (შესამჩნევია რომ ამ შემთხვევაში map-ის საერთო performance გაუარესდება, რადგან ელემენტის ჩასმაც და წაკითხვაც უფრო დიდ დროს წაიღებს).

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

მაგალითში, Person ტიპის ობიექტი გვქონდეს HashMap-ის გასაღებად, ხოლო მნიშვნელობები იყოს String.
ახლა კი მოვახდინოთ კოლიზია.
ამ კოდმა საკმაოდ მძლავრ კომპიუტერზე მუშაობას მოანდომა 2.5 საათი და საბოლოოდ ელემენტის წაკითხვამ კი დაახლოებით 40 მილიწამი. ახლა, ყოველგვარი წინასწარი ახნის გარეშე მოდით მოვახდინოთ Peron კლასის მცირე ცვლილება, მოდით მან იმპლემენტაცია გაუკეთოს Comparable<Person> ინტერფეისს და Person კლასში დავამატოთ კოდის შემდეგი ფრაგმენტი 
ზემოთ აღნიშნულმა კოდმა, იმავე კომპიუტერზე, მუშაობას მოანდომა ერთ წუთზე ნაკლები და საბოლოოდ ელემენტის წაკითხვას 1 მილიწამი - ანუ ის 150-ჯერ სწრაფად მუშაობს ამ შემთხვევაში. 

მოდით ახლა ავხსნათ რა მოხდა. როგორც დასაწყისში აღვნიშნეთ, Java 8-ში წინა ვერსიებთან შედარებით ბევრი კლასი გაუმჯობესდა. Java 7-ში კოლიზირებული (ერთი და იმავე hashCode-ის მქონე ელემენტები) ინახებოდა bucket-ში რომლის სტრუქტურაც იყო LinkedList. Java 8-დან დაწყებული, თუ კოლიზირებული ელემენტების რიცხვი არის გარკვეულ რიცხვზე მეტი (ეს რიცხვი არის 8), და Map-ის capacity არის 64-ზე მეტი, მაშინ HashMap-ის იმპლემენტაცია LinkedList-ის ნაცვლად იქნება BinaryTree.

აქ გაგვიჩნდება აზრი, რომ non-comparable გასაღებების შემთხვევაში, ეს ხე იქნება არაბალანსირებული, მაშინ როცა სხვა შემთხვევაში ის იქნება მეტ-ნაკლებად ბალანსირებული. მაგრამ ეს არ შეესაბამება სიმართლეს. Tree-ის იმპლემენტაცია HashMap-ში არის Red-Black Tree, რაც იმას ნიშნავს, რომ ის ყოველთვის არის ბალანსირებული. თუ ჩვენ დავწერთ utility კლასს, რომელიც ზემთ აღნიშნული მაგალითისთვის შეამოწმებს ხის სიღრმეს, ის იქნება 19.

ახლა მთავარი კითხვა, როგორ მივიღეთ ასეთი დიდი განსხვავება Comparable ინტერფესისის იმპლემენტაციით ? როცა HashMap ცდილობს იპოვოს ხეში ახალი ელემენტისთვის ადგილი, ის ამოწმებს ახალი და ძველი ელემენტები (უკვე არსებული) არის თუ არა ადვილად სადარი (Comparable interface). ჩვენი მაგალითის პირველ შემთხვევაში ის იძახებს tieBreakOrder(Object a, Object b) მეთოდს. ეს მეთოდი პირველად ცდილობს ობიექტების შედარებას class name-ზე დაყრდნობით, და შემდეგ იყენებს System.identityHashCode-ს. მაგრამ, როცა გასაღები აიმპლემენტირებს Comparable-ს ეს პროესი გაცილებით მარტივია. გასაღები (key), თვითონვე განსაზღვრავს როგორ უნდა შეედაროს სხვა ელემენტს და ელემენტის ჩამატება და წაკითხვა უფრო სწრაფად ხდება.  tieBreakOrder(Object a, Object b)  მეთოდის გამოძახება ხდება მხოლოდ მაშინ თუ ორი ელემენტის compareTo მეთოდი დააბრუნებს 0-ს (ანუ თუ ტოლია).

რომ შევაჯამოთ, Java 8-ში, თუ HashMap-ის bucket-ში ელემენტების რიცხვა გადააჭარბა 8-ს და HashMap-ის ზომამ 64-ს, მაშინ bucket-ის იმპლემენტაცია LinkedList-ის ნაცვლად იქნება Red-Black Tree, რომელიც ყოველთვის დაბალანსებულია და თუ Map-ის გასაღები აიმპლემენტირებს Comparable-ს, მაშინ ელემენტის ჩამატება და წაკითხვა იქნება გაცილებით სწრაფი. მაგრამ უნდა აღინიშნოს ისიც, რომ თუ კოლიზიების რიცხვი არც ისე დიდია, Comparable/ non-Comparable იდეას უკვე დიდი აზრი აღარ აქვს.


Friday, April 6, 2018

TEDxKazimierz - organization which gives me a lot

Firstly, I want to mention that as soon as I arrived in Poland there was a feeling how can I adapt the situation ? Although, I think that I am sociable and communicable person, it is not so easy to adapt new country and new culture even there is big and long term friendship between Georgia and Poland. Adaptation was easier than I expected. 


After couple of months I saw an event on Facebook that in Kraków it was going to held TedXKazimerz Salon. During my spare time I watch TedX and I can say that more or less I know the idea of it. But that’s not all. I also saw that there was an opportunity to be volunteer. It was great chance for me to meet new people and new friends. I communicated one of the organizers, Bogusia, and I joined the team of volunteers. Since that time, I have taken part in three Salons, I met dozens of people and also improve my skills in different fields.


As I mentioned in the beginning, TedXKazimerz is the organization which unites lots of young people not only from Poland. This is the thing what I like. You have chance to share your ideas with different people, listen their arguments and this makes you better, this grows you professionally, this helps you to look things in other way and these kind of events are building new ideas and new chances in our life. Everything is based on respect and appreciation. 

Sunday, March 4, 2018

TEDxKazimierz Salons in Krakow

ალბათ, ყველამ თუ არა, ბევრმა მაინც იცის ზოგადად TEDx-ის შესახებ, თუ არ იცით, შეგიძლიათ გაეცნოთ აქ. ეს არის პორტალი, რომელიც აერთიანებს ბევრ საინტერესო სხვადასხვა შინაარსის მქონე მოხსენებას(talk-ს).

რამდენიმე წელია უკვე აქტიურად ვარ ამ საიტის მომხმარებელი, თუმცა იმას ვერასდროს წარმოვიდგენდი, რომ რაიმე სახით TEDx-ის გუნდში აღმოვჩნდებოდი. მოკლედ TEDxKazimierz არის ორგანიზაცია, რომელსაც აქვს ოფიციალური უფლება TEDx-დან რომ ჩაატაროს Salon-ები.  2018-ში უკვე ორი სალონი იყო, რომელსაც "გამახურებელი" ხასიათი უფრო ჰქონდა, რადგან წინ უფრო ბევრი საინტერესო სალონი გველის.

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

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

TEDxKazimierz-ის ოფიციალური Facebook გვერდი
TEDxKazimierz-ის ოფიციალური ვებ გვერდი

Sunday, February 11, 2018

ნუ იქნები პროკრასტინატორი ანუ ხვალემენი

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


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

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

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

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

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

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