অ্যাবস্ট্রাকশনগুলির কি কোড পাঠযোগ্যতা হ্রাস করতে হবে?


19

আমি কাজ করি এমন একজন ভাল বিকাশকারী আমাদের উত্তরাধিকার সূত্রে প্রাপ্ত কিছু কোডে একটি বৈশিষ্ট্য প্রয়োগ করতে তার যে অসুবিধা হয়েছিল সে সম্পর্কে সম্প্রতি আমাকে বলেছিলেন; তিনি বলেন যে সমস্যাটি ছিল কোডটি অনুসরণ করা কঠিন। এর থেকে, আমি পণ্যের আরও গভীরভাবে দেখেছি এবং বুঝতে পেরেছি যে কোডের পথটি দেখতে কতটা কঠিন।

এটি এতগুলি ইন্টারফেস এবং বিমূর্ত স্তর ব্যবহার করেছিল যে জিনিসগুলি কোথায় শুরু হয়েছে এবং শেষ হয়েছে তা বোঝার চেষ্টা করা বেশ কঠিন। আমি অতীতের প্রকল্পগুলি দেখেছি (আমি পরিষ্কার কোড নীতি সম্পর্কে এতটা সচেতন হওয়ার আগে) এবং প্রকল্পটিতে ঘুরতে পারা খুব কঠিন বলে মনে হয়েছিল, মূলত কারণ আমার কোড নেভিগেশন সরঞ্জামগুলি আমাকে সবসময় একটি ইন্টারফেসে নিয়ে যায়। কংক্রিট বাস্তবায়ন বা যেখানে কিছু প্লাগইন ধরণের আর্কিটেকচারে কিছুটা ওয়্যার্ড হয়েছিল তা সন্ধান করতে অতিরিক্ত অতিরিক্ত প্রচেষ্টা লাগবে।

আমি জানি কিছু বিকাশকারী খুব নির্ভর করে এই কারণেই নির্ভরতা ইনজেকশন পাত্রে সরিয়ে রাখেন। এটি সফ্টওয়্যারটির পথটিকে এতটাই বিভ্রান্ত করে যে কোড নেভিগেশনের অসুবিধা তাত্পর্যপূর্ণভাবে বেড়ে যায়।

আমার প্রশ্ন হ'ল: যখন কোনও কাঠামো বা প্যাটার্ন এ জাতীয় এতগুলি ওভারহেড উপস্থাপন করে, তখন কি এটি মূল্যবান? এটি কি খারাপভাবে প্রয়োগ করা প্যাটার্নের লক্ষণ?

আমার ধারণা, কোনও বিকাশকারী হতাশা কাটিয়ে উঠতে সহায়তা করতে সেই বিমূর্ততা প্রকল্পে কী নিয়ে আসে তার বৃহত্তর চিত্রটি সন্ধান করা উচিত। সাধারণত যদিও, তাদের সেই বড় ছবিটি দেখাতে অসুবিধা হয়। আমি জানি আমি টিডির সাথে আইওসি এবং ডিআইয়ের প্রয়োজনীয়তা বিক্রি করতে ব্যর্থ হয়েছি। এই বিকাশকারীদের জন্য, এই সরঞ্জামগুলির ব্যবহার কেবল কোডের পাঠযোগ্যতার পক্ষে খুব বেশি বাধা দেয়।

উত্তর:


17

এটি সত্যিই @ কেভিন ক্লাইনের উত্তরের দীর্ঘ মন্তব্যের বেশি।

যদিও ভাষাগুলি নিজেরাই অগত্যা এটির কারণ বা প্রতিরোধ করে না, আমি মনে করি যে তার ধারণার সাথে কিছু আছে যে এটি ভাষা (বা কমপক্ষে ভাষা সম্প্রদায়ের) এর সাথে কিছুটা হলেও সম্পর্কিত। বিশেষত, যদিও আপনি বিভিন্ন ভাষায় একই সমস্যাটি সাজানোর পক্ষে চালাতে পারেন, এটি প্রায়শই বিভিন্ন ভাষায় ভিন্ন ভিন্ন রূপ নেবে।

উদাহরণস্বরূপ, আপনি যখন সি ++ তে এটি চালাবেন তখন সম্ভাবনা বেশি থাকে যে এটি খুব বেশি বিমূর্ততার ফলস্বরূপ, এবং খুব বেশি চালাকতার ফলস্বরূপ। যেমন উদাহরণস্বরূপ, প্রোগ্রামার একটি বিশেষ পুনরুক্তিতে এটির (যা আপনি খুঁজে পাচ্ছেন না) ঘটছে এমন গুরুত্বপূর্ণ পরিবর্তনটি লুকিয়ে রেখেছে, তাই দেখে মনে হচ্ছে এটি কেবল এক স্থান থেকে অন্য জায়গায় ডেটা অনুলিপি করছে এমন অনেকগুলি পার্শ্ব প্রতিক্রিয়া রয়েছে যাগুলির কিছুই নেই really তথ্য যে অনুলিপি সঙ্গে না। কেবল জিনিস আকর্ষণীয় রাখতে, এই আউটপুটটির সাথে আন্তঃবিবাহিত হয় যা এক ধরণের বস্তুতে অন্য প্রকারে কাস্টিংয়ের সময় অস্থায়ী বস্তু তৈরির পার্শ্ব প্রতিক্রিয়া হিসাবে তৈরি করা হয়।

বিপরীতে, যখন আপনি জাভাতে এটি চালাবেন, আপনি সম্ভবত আরও পরিচিত "এন্টারপ্রাইজ হ্যালো ওয়ার্ল্ড" এর কিছু বৈচিত্র দেখতে পাচ্ছেন, যেখানে একক তুচ্ছ শ্রেণীর পরিবর্তে যা কিছু সহজ করে, আপনি একটি বিমূর্ত বেস শ্রেণি পেতে পারেন এবং একটি কংক্রিট উদ্ভূত শ্রেণি যা ইন্টারফেস এক্স প্রয়োগ করে এবং একটি ডিআই কাঠামোয় একটি কারখানা শ্রেণীর দ্বারা তৈরি করা হয়, ইত্যাদি। আসল কাজ করে এমন 10 টি লাইন কোড অবকাঠামোর 5000 লাইনের নিচে সমাহিত করা হয়।

এর কয়েকটি পরিবেশের উপর নির্ভর করে কমপক্ষে ভাষার হিসাবে - এক্স 11 এবং এমএস উইন্ডোজের মতো উইন্ডোটিং পরিবেশের সাথে সরাসরি কাজ করা তুচ্ছ "হ্যালো ওয়ার্ল্ড" প্রোগ্রামটিকে প্রায় অনিবার্য আবর্জনার 300+ লাইনে পরিণত করার জন্য কুখ্যাত। সময়ের সাথে সাথে, আমরা সেগুলি থেকেও আমাদের উত্তাপের জন্য বিভিন্ন টুলকিটগুলি বিকাশ করেছি - তবে 1) এই সরঞ্জামদণ্ডগুলি নিজেরাই বেশ তুচ্ছ, এবং 2) শেষ ফলাফলটি এখনও কেবল বৃহত্তর এবং আরও জটিল নয়, তবে সাধারণত কম নমনীয়ও হয় is একটি পাঠ্য-মোড সমতুল্য (উদাহরণস্বরূপ, যদিও এটি কিছু পাঠ্য মুদ্রণ করেও, এটি কোনও ফাইলে পুনর্নির্দেশ করা খুব কমই সম্ভব / সমর্থিত)।

মূল প্রশ্নের উত্তরের (কমপক্ষে একটি অংশ) উত্তর দেওয়ার জন্য: কমপক্ষে আমি যখন এটি দেখেছি তখন হাতে থাকা কাজের পক্ষে অনুপযুক্ত একটি প্যাটার্নটি প্রয়োগ করার চেয়ে কোনও নিদর্শনকে দুর্বলভাবে প্রয়োগ করার বিষয়টি কম ছিল - সর্বাধিক প্রায়শই এমন কিছু প্যাটার্ন প্রয়োগ করার চেষ্টা করা যায় যা একটি প্রোগ্রামে অপরিহার্যভাবে বিশাল এবং জটিল হিসাবে কার্যকর হতে পারে তবে একটি ছোট সমস্যা প্রয়োগের সাথে সাথে এটি বিশাল এবং জটিলও হয়ে যায়, যদিও এই ক্ষেত্রে আকার এবং জটিলতা সত্যই এড়ানো সম্ভব ছিল না though ।


7

আমি দেখতে পেলাম যে প্রায়শই ইয়াজিএনআই পদ্ধতি গ্রহণ না করার কারণে এটি ঘটে । ইন্টারফেসের মধ্য দিয়ে যাচ্ছুক সমস্ত কিছুই, যদিও কেবলমাত্র একটি কংক্রিট বাস্তবায়ন এবং অন্যকে পরিচয় করানোর কোনও বর্তমান পরিকল্পনা নেই, এমন জটিলতা যুক্ত করার একটি প্রধান উদাহরণ যা আপনার দরকার নেই। এটি সম্ভবত ধর্মবিরোধী তবে আমি নির্ভরতা ইনজেকশনের প্রচুর ব্যবহার সম্পর্কে একইরকম অনুভব করি।


YAGNI উল্লেখ করার জন্য +1 এবং একক রেফারেন্স পয়েন্ট সহ বিমূর্ততা। বিমূর্ততা তৈরির প্রাথমিক ভূমিকাটি একাধিক জিনিসের সাধারণ বিষয়টি ফ্যাক্টর করা। যদি কোনও বিমূর্ততা কেবলমাত্র একটি বিন্দু থেকে রেফারেন্স করা হয়, আমরা সাধারণ জিনিসগুলি ফ্যাক্টরিংয়ের কথা বলতে পারি না, এর মতো একটি বিমূর্ততা কেবল ইয়োও সমস্যায় অবদান রাখে। আমি এটি প্রসারিত করব কারণ এটি সমস্ত ধরণের বিমূর্ততার জন্য সত্য: ফাংশন, জেনেরিক্স, ম্যাক্রোস যাই হোক না কেন ...
কলমারিয়াস

3

ভাল, যথেষ্ট বিমূর্ততা নয় এবং আপনার কোডটি বোঝা শক্ত কারণ আপনি কোন অংশগুলি কী করে তা আলাদা করতে পারবেন না।

অত্যধিক বিমূর্ততা এবং আপনি বিমূর্ততাটি দেখতে পান তবে কোডটি নিজেই নয়, এবং এরপরে বাস্তব এক্সিকিউশন থ্রেডটি অনুসরণ করা শক্ত করে তোলে।

ভাল বিমূর্ততা অর্জনের জন্য, আপনার কেআইএসএস করা উচিত: এই জাতীয় সমস্যাগুলি এড়াতে কী অনুসরণ করতে হবে তা জানতে আমার এই প্রশ্নের উত্তর দেখুন

আমি মনে করি যে আপনার বর্ণনাকারী মামলার সন্ধানের জন্য গভীর শ্রেণিবিন্যাস এবং নামকরণ এড়ানো সবচেয়ে গুরুত্বপূর্ণ বিষয়। যদি বিমূর্তিগুলির নামকরণ করা হয়, তবে আপনাকে খুব গভীরে যেতে হবে না, কেবল বিমূর্ত স্তরটিতে যেতে হবে যেখানে কী ঘটেছিল তা আপনার বুঝতে হবে। নামকরণ আপনাকে বিস্তারের এই স্তরটি কোথায় তা সনাক্ত করতে দেয়।

নিম্ন স্তরের কোডে সমস্যা দেখা দেয়, যখন আপনার সত্যিকারের সমস্ত প্রক্রিয়াটি বোঝার দরকার হয়। তারপরে, পরিষ্কারভাবে বিচ্ছিন্ন মডিউলগুলির মাধ্যমে এনক্যাপসুলেশনই কেবল সহায়তা help


3
ভাল, যথেষ্ট বিমূর্ততা নয় এবং আপনার কোডটি বোঝা শক্ত কারণ আপনি কোন অংশগুলি কী করে তা আলাদা করতে পারবেন না। এটি এনক্যাপসুলেশন, বিমূর্ততা নয়। আপনি কোনও বিমূর্ততা ছাড়াই কংক্রিটের ক্লাসে অংশগুলি আলাদা করতে পারেন।
বিবৃতি

ক্লাসগুলি কেবলমাত্র আমরা ব্যবহার করছি এমন বিমূর্ততা নয়: ফাংশন, মডিউল / লাইব্রেরি, পরিষেবাদি ইত্যাদি your
ক্লাইম

1
@ স্টেটমেন্ট: এনক্যাপসুলেটিং ডেটা অবশ্যই একটি বিমূর্ততা।
এড এস

যদিও নেমস্পেসের হায়ারারচিগুলি সত্যিই দুর্দান্ত।
জ্যাব

2

আমার জন্য এটি একটি সংযোগের সমস্যা এবং ডিজাইনের গ্রানুলারিটি সম্পর্কিত। এমনকি মিলনের সবচেয়ে শিথিল রূপটি একটি জিনিস থেকে অন্যটিতে নির্ভরতার পরিচয় দেয়। এটি যদি কয়েক হাজার থেকে হাজার হাজার অবজেক্টের জন্য করা হয়, যদিও তারা সমস্ত তুলনামূলকভাবে সহজ, এসআরপি মেনে চলা এবং সমস্ত নির্ভরতা স্থিতিশীল বিমূর্তির দিকে প্রবাহিত হলেও, এটি একটি কোডবেস দেয় যা একটি আন্তঃসম্পর্কিত পুরো হিসাবে যুক্তি করা খুব কঠিন।

এমন ব্যবহারিক জিনিসগুলি রয়েছে যা আপনাকে কোনও কোডবেসের জটিলতা নির্ধারণ করতে সহায়তা করে, তাত্ত্বিক এসইতে প্রায়শই আলোচিত হয় না, যেমন শেষ পর্যায়ে পৌঁছানোর আগে আপনি কল স্ট্যাকের গভীরতা কতটা পেতে পারেন এবং আপনি যা করার আগে আপনাকে কতটা গভীরভাবে যেতে হবে, এর সাথে আত্মবিশ্বাসের একটি মহান বিষয়, কোনও ব্যতিক্রমের ঘটনা সহ কল ​​স্ট্যাকের সেই স্তরে ঘটতে পারে এমন সমস্ত সম্ভাব্য পার্শ্ব প্রতিক্রিয়াগুলি বুঝতে understand

এবং আমি খুঁজে পেয়েছি, কেবল আমার অভিজ্ঞতার মধ্যে, অল্প অল্প কল স্ট্যাকযুক্ত চাটুকার সিস্টেমগুলি সম্পর্কে বিতর্ক করা খুব সহজ হতে থাকে। চূড়ান্ত উদাহরণ হ'ল একটি সত্তা-উপাদান সিস্টেম যেখানে উপাদানগুলি কেবল কাঁচা ডেটা। কেবলমাত্র সিস্টেমগুলির কার্যকারিতা রয়েছে এবং ইসিএস প্রয়োগ ও ব্যবহারের প্রক্রিয়ায় আমি এটিকে এখনও সবচেয়ে সহজ সিস্টেম হিসাবে খুঁজে পেয়েছি, কারণ কয়েক হাজার সিস্টেমের কয়েক হাজার লাইনের বিস্তৃত জটিল কোডবেসগুলি কয়েক ডজন সিস্টেমে ফোটায় যে সম্পর্কে সমস্ত কার্যকারিতা ধারণ করে।

অনেকগুলি জিনিস কার্যকারিতা সরবরাহ করে

পূর্ববর্তী কোডবেসে কাজ করার আগে বিকল্প ছিল কয়েক শতাধিক বাল্ক সিস্টেমের বিপরীতে কয়েক থেকে একাধিক ক্ষুদ্র ক্ষুদ্র বস্তু সহ এমন একটি সিস্টেম যা কেবলমাত্র একটি বস্তু থেকে অন্য বস্তুর কাছে বার্তা প্রেরণের জন্য ব্যবহৃত কিছু বস্তুর সাথে ব্যবহৃত হত ( Messageবস্তু, উদাহরণস্বরূপ, যার এটি ছিল) নিজস্ব পাবলিক ইন্টারফেস)। আপনি যখন ইসিএসকে এমন একটি বিন্দুতে ফিরিয়ে দেন যখন উপাদানগুলির কার্যকারিতা থাকে এবং কোনও সত্তায় উপাদানগুলির প্রতিটি অনন্য সংমিশ্রণ তার নিজস্ব অবজেক্টের ধরণের ফল দেয় তখন মূলত আপনি অ্যানালগালিটি পান ically এবং এটি ছোট, সহজ ফাংশনগুলি উত্তরাধিকার সূত্রে প্রাপ্ত এবং অবৈধ ধারণাগুলির মডেল যা অবাস্তব ধারণাগুলি ( Particleঅবজেক্ট বনাম) মডেল করে providedPhysics System, যেমন)। তবে আন্তঃ নির্ভরতাগুলির একটি জটিল গ্রাফও পাওয়া যায় যা বিস্তৃত স্তর থেকে কী ঘটেছিল তা নিয়ে तर्क করা কঠিন করে তোলে, কেবল কারণ কোডবেজে এমন অনেক কিছুই রয়েছে যা আসলে কিছু করতে পারে এবং তাই কিছু ভুল করতে পারে - - প্রকারগুলি যা "ডেটা" প্রকার নয়, তবে সম্পর্কিত কার্যকারিতা সহ "অবজেক্ট" প্রকার। সম্পর্কিত কোনও কার্যকারিতা ছাড়াই বিশুদ্ধ ডেটা হিসাবে পরিবেশন করা ধরণগুলি ভুল হতে পারে না কারণ তারা নিজেরাই কিছু করতে পারে না।

খাঁটি ইন্টারফেসগুলি এই বোধগম্যতার সমস্যাটিকে এতটা সহায়তা করে না কারণ এটি "সংকলন-সময় নির্ভরতা" কম জটিল করে তোলে এবং পরিবর্তন এবং প্রসারণের জন্য আরও শ্বাসকষ্ট সরবরাহ করে, এটি "রানটাইম নির্ভরতা" এবং ইন্টারঅ্যাকশনগুলিকে কোনও কম জটিল করে তোলে না। ক্লায়েন্ট অবজেক্টটি এখনও কংক্রিট অ্যাকাউন্ট অবজেক্টে কল করা সত্ত্বেও তাদেরকে অনুরোধ করা ফাংশনগুলি শেষ করে IAccount। পলিমারফিজম এবং অ্যাবস্ট্রাক্ট ইন্টারফেসগুলির ব্যবহার রয়েছে তবে তারা এমনভাবে জিনিসগুলিকে ডিকুয়াল করে না যা আপনাকে কোনও নির্দিষ্ট সময়ে যেতে পারে এমন সমস্ত পার্শ্ব প্রতিক্রিয়াগুলির বিষয়ে যুক্তিযুক্তভাবে সত্যই সহায়তা করে। এই ধরণের কার্যকর ডিকোপলিং অর্জন করার জন্য আপনার একটি কোডবেস দরকার যা কার্যকারিতা সহ অনেক কম জিনিস রাখে।

আরও ডেটা, কার্যকারিতা কম

সুতরাং আমি ইসিএস পদ্ধতির সন্ধান পেয়েছি, এমনকি আপনি এটি সম্পূর্ণরূপে প্রয়োগ না করেও চূড়ান্ত সহায়ক হতে পারেন, যেহেতু এটি পরিণত হয় শত শত বস্তুগুলি কেবলমাত্র বিশাল আকারের সিস্টেমের সাথে কাঁচা ডেটাতে পরিণত হত, আরও মোটাভাবে নকশাকৃত, যা সমস্ত সরবরাহ করে কার্যকারিতা। এটি "ডেটা" প্রকারের সংখ্যা সর্বাধিক করে তোলে এবং "অবজেক্ট" ধরণের সংখ্যা হ্রাস করে এবং তাই আপনার সিস্টেমে এমন জায়গাগুলির সংখ্যা একেবারে হ্রাস করে যা আসলে ভুল হতে পারে। শেষ ফলাফলটি হ'ল একটি "সমতল" সিস্টেম যা নির্ভরশীলতার জটিল গ্রাফ ছাড়াই, কেবলমাত্র উপাদানগুলির জন্য সিস্টেম, কখনও তদ্বিপরীত হয় না এবং অন্য উপাদানগুলির সাথে কখনই উপাদান হয় না। এটি মূলত অনেক বেশি কাঁচা ডেটা এবং অনেক কম অ্যাবস্ট্রাকশন যার প্রভাব রয়েছে মূল কোডগুলি, কী বিমূর্তিগুলিতে কোডবেসের কার্যকারিতাকে কেন্দ্রিয়করণ এবং সমতলকরণের।

30 টি সহজ জিনিস 1 টিরও বেশি জটিল বিষয় নিয়ে যুক্তিযুক্ত হওয়া সহজভাবে সহজ নয়, যদি 30 টি সহজ জিনিস আন্তঃসম্পর্কিত হয় যখন জটিল জিনিসটি তার নিজের উপর দাঁড়িয়ে থাকে। সুতরাং আমার পরামর্শটি হ'ল বস্তুগুলির মধ্যে মিথস্ক্রিয়া থেকে আরও বেশি কিছুকে বাল্কিয়ার অবজেক্টের দিকে স্থানান্তর করা যা ভর ডিকোপলিং অর্জনের জন্য অন্য কোনও কিছুর সাথে ইন্টারঅ্যাক্ট করতে হবে না, পুরো "সিস্টেমে" (একচেটিয়া এবং godশ্বরের বস্তু নয়, আপনাকে মনে রাখবেন, এবং 200 পদ্ধতি সহ ক্লাস নয়, তবে একটি সংক্ষিপ্ত ইন্টারফেস থাকা সত্ত্বেও একটি Messageবা একটি এর চেয়ে যথেষ্ট উচ্চ স্তরের কিছু Particle)। এবং আরও সাধারণ প্লেইন পুরানো ডেটা প্রকারের পক্ষে আপনি তাদের উপর যত বেশি নির্ভরশীল, কম সংযোগ আপনি পাবেন। এমনকি যদি এটি কিছু এসই ধারণার বিরোধিতা করে তবে আমি খুঁজে পেয়েছি এটি সত্যিই অনেক সাহায্য করে।


0

আমার প্রশ্নটি হচ্ছে, যখন কোনও কাঠামো বা প্যাটার্নটি এত বেশি ওভারহেডের পরিচয় দেয়, তখন কি এটি মূল্যবান? এটি কি খারাপভাবে প্রয়োগ করা প্যাটার্নের লক্ষণ?

হতে পারে এটি ভুল প্রোগ্রামিংয়ের ভাষা বেছে নেওয়ার লক্ষণ।


1
পছন্দের ভাষার সাথে এটির কীভাবে কিছু আছে তা আমি দেখতে পাচ্ছি না। বিমূর্ততা একটি উচ্চ স্তরের ভাষা-স্বাধীন ধারণা।
এড এস

@ এড: কিছু বিমূর্ততা অন্যের চেয়ে কিছু ভাষায় আরও সহজভাবে উপলব্ধিযোগ্য।
কেভিন ক্লাইনে

হ্যাঁ, তবে এর অর্থ এই নয় যে আপনি সেই ভাষাগুলিতে একটি নিখুঁত রক্ষণাবেক্ষণযোগ্য এবং সহজে বোঝা বিমূর্ততা লিখতে পারবেন না। আমার বক্তব্যটি ছিল আপনার উত্তরটি প্রশ্নের উত্তর দেয় না বা কোনওভাবেই ওপিকে সহায়তা করে না।
এড এস

0

নকশা নিদর্শনগুলির নিম্নতর বোঝাপড়া এই সমস্যার একটি প্রধান কারণ হয়ে থাকে। আমি এই ইয়ো-ইনিংয়ের জন্য সবচেয়ে খারাপ দেখেছি এবং এর মধ্যে খুব বেশি কংক্রিটের ডেটা ছাড়াই ইন্টারফেস থেকে ইন্টারফেসে বাউন্স করা হয়েছে ওরাকলের গ্রিড নিয়ন্ত্রণের জন্য একটি এক্সটেনশন।
এটি সত্যিই দেখে মনে হয়েছিল যেন আমার জাভা কোড জুড়ে কারও কোনও বিমূর্ত কারখানা পদ্ধতি এবং ডেকোরেটর প্যাটার্ন প্রচণ্ড উত্তেজনা ছিল। এবং এটি আমাকে কেবল ফাঁকা এবং একা বোধ করতে লাগল।


-1

আমি আইডিই বৈশিষ্ট্যগুলি ব্যবহারের বিরুদ্ধে সাবধানতা অবলম্বন করব যা এটি বিমূর্ত জিনিসগুলিকে সহজ করে তোলে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.