ওভাররাইডিং কংক্রিটের পদ্ধতিগুলি কি কোনও গন্ধের গন্ধ?


31

এটি কি সত্য যে ওভাররাইডিং কংক্রিটের পদ্ধতিগুলি একটি কোড গন্ধ? কারণ আমি মনে করি আপনার যদি কংক্রিটের পদ্ধতিগুলি ওভাররাইড করার প্রয়োজন হয়:

public class A{
    public void a(){
    }
}

public class B extends A{
    @Override
    public void a(){
    }
}

এটি আবার লিখতে পারে

public interface A{
    public void a();
}

public class ConcreteA implements A{
    public void a();
}

public class B implements A{
    public void a(){
    }
}

এবং খ যদি ক এ () এ পুনরায় ব্যবহার করতে চায় তবে এটি আবার লিখতে পারে:

public class B implements A{
    public ConcreteA concreteA;
    public void a(){
        concreteA.a();
    }
}

পদ্ধতিটি ওভাররাইড করার জন্য যার উত্তরাধিকারের প্রয়োজন হয় না, এটি কি সত্য?



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

5
প্রশ্নটি জাভা ট্যাগ করা হয়নি, তবে কোডটি জাভা হিসাবে দেখা যাচ্ছে। সি # (বা সি ++) এ আপনাকে virtualওভাররাইডগুলি সমর্থন করার জন্য কীওয়ার্ডটি ব্যবহার করতে হবে । সুতরাং, ভাষাটির বর্ণনাগুলি দ্বারা বিষয়টি আরও (বা কম) অস্পষ্ট করে তুলেছে।
এরিক tদ

1
দেখে মনে হয় প্রায় প্রতিটি প্রোগ্রামিং ভাষার বৈশিষ্ট্যটি অবশ্যম্ভাবীভাবে পর্যাপ্ত বছর পরে "কোড গন্ধ" হিসাবে শ্রেণীবদ্ধ করা শেষ করে।
ব্র্যান্ডন

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

উত্তর:


34

না এটি কোনও কোডের গন্ধ নয়।

  • যদি কোনও শ্রেণি চূড়ান্ত না হয় তবে এটি উপক্লাস করার অনুমতি দেয়।
  • যদি কোনও পদ্ধতি চূড়ান্ত না হয় তবে এটি ওভাররাইড করার অনুমতি দেয়।

সাবক্লাসিং উপযুক্ত কিনা এবং কোন পদ্ধতিগুলি ওভাররাইড করা যেতে পারে তা সাবধানতার সাথে বিবেচনা করা প্রতিটি শ্রেণীর দায়িত্বশীলতার মধ্যে রয়েছে

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

ওভাররাইড পদ্ধতিগুলির ক্ষেত্রে সাধারণ ক্ষেত্রে হ'ল বেস শ্রেণিতে একটি ডিফল্ট বাস্তবায়ন যা সাবক্লাসে কাস্টমাইজ বা অপ্টিমাইজ করা যেতে পারে (বিশেষত জাভা 8 এ ইন্টারফেসে ডিফল্ট পদ্ধতিগুলির আগমন সহ)।

class A {
    public String getDescription(Element e) {
        // return default description for element
    }
}

class B extends A {
    public String getDescription(Element e) {
        // return customized description for element
    }
}

ওভাররাইড আচরণের একটি বিকল্প কৌশল প্যাটার্ন , যেখানে আচরণটি ইন্টারফেস হিসাবে বিমূর্ত করা হয় এবং প্রয়োগটি শ্রেণিতে সেট করা যেতে পারে।

interface DescriptionProvider {
    String getDescription(Element e);
}

class A {
    private DescriptionProvider provider=new DefaultDescriptionProvider();

    public final String getDescription(Element e) {
       return provider.getDescription(e);
    }

    public final void setDescriptionProvider(@NotNull DescriptionProvider provider) {
        this.provider=provider;
    }
}

class B extends A {
    public B() {
        setDescriptionProvider(new CustomDescriptionProvider());
    }
}

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

আপনার শেষ উদাহরণে, Aপ্রয়োগগুলি করা উচিত নয় DescriptionProvider?
স্পট করেছেন

@Spotted: A পারে বাস্তবায়ন DescriptionProvider, এবং এইভাবে ডিফল্ট বিবরণ প্রদানকারী হও। তবে এখানে ধারণাটি উদ্বেগের বিচ্ছেদ: Aঅন্যান্য বাস্তবায়নগুলি তাদের সরবরাহ করার সাথে সাথে বর্ণনাটির প্রয়োজন (কিছু অন্যান্য শ্রেণিও হতে পারে) needs
পিটার ওয়ালসার

2
ঠিক আছে, কৌশল প্যাটার্নের মতো আরও শোনাচ্ছে ।
চিতল

@ স্পটেড: আপনি ঠিক বলেছেন, উদাহরণটি কৌশল প্যাটার্নকে চিত্রিত করে, ডেকোরেটার প্যাটার্নটি নয় (কোনও সাজসজ্জা একটি উপাদানকে আচরণ যুক্ত করবে)। আমি আমার উত্তরটি সংশোধন করব, ধন্যবাদ।
পিটার ওয়ালসার

25

এটি কি সত্য যে ওভাররাইডিং কংক্রিটের পদ্ধতিগুলি একটি কোড গন্ধ?

হ্যাঁ, সাধারণভাবে, কংক্রিটের পদ্ধতিগুলিকে ওভাররাইড করা কোডের গন্ধ।

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

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

অতএব, এটি আমার কাছে দুর্গন্ধযুক্ত বলে মনে হয় - কখনও কখনও ভাল, সাধারণত খারাপ, নিশ্চিত হয়ে দেখুন।


29
আপনার ব্যাখ্যাটি ঠিক আছে, তবুও আমি ঠিক ঠিক বিপরীত উপসংহারে এসে পৌঁছেছি: "না, কংক্রিটের পদ্ধতিগুলিকে ওভাররাইড করা সাধারণভাবে কোনও কোডের গন্ধ নয় " - যখন কোনও ওভাররাইড পদ্ধতিগুলি ওভাররাইড করার উদ্দেশ্যে নয় তখনই এটি একটি কোড গন্ধ। ;-)
ডক ব্রাউন

2
@ ডকব্রাউন অবিকল! আমি এও দেখছি যে ব্যাখ্যাটি (এবং বিশেষত উপসংহার) প্রাথমিক বক্তব্যের বিরোধিতা করে।
টেরোসোরাসগুলি

1
@ স্পটেড: সর্বাধিক কাউন্টারিক্স নমুনা এমন একটি Numberক্লাস যা increment()তার পরবর্তী বৈধ মানকে মান সেট করে। যদি আপনি এটিকে সাবক্লাস করেন EvenNumberযেখানে increment()একের পরিবর্তে দুটি যোগ করা হয় (এবং সেটারটি স্নেহ জোর করে), ওপির প্রথম প্রস্তাবটিতে ক্লাসের প্রতিটি পদ্ধতির নকল রূপায়ন প্রয়োজন হয় এবং তার দ্বিতীয়টির সদস্যকে পদ্ধতিগুলি কল করার জন্য র্যাপার পদ্ধতিগুলি লেখার প্রয়োজন হয়। উত্তরাধিকারের উদ্দেশ্য অংশটি হ'ল শিশু শ্রেণীগুলি কেবল সেই পদ্ধতিগুলি পৃথক করতে হবে যা তাদের পিতামাতার থেকে আলাদা হয় তা স্পষ্ট করে দেওয়া।
blrfl

5
@ ডকব্রাউন: একটি কোড গন্ধ হওয়ার অর্থ এই নয় যে কোনও কিছু অগত্যা খারাপ, কেবল এটিই সম্ভবত
মিকোয়াক

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

7

আপনার যদি কংক্রিটের পদ্ধতিগুলি ওভাররাইড করার প্রয়োজন হয় [...] এটি আবার লিখতে পারে

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

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


ক্লাস এ যদি উত্পন্ন করার নকশা করা হত, তবে অভিপ্রায়টি স্পষ্টভাবে প্রকাশ করার জন্য কোনও বিমূর্ত পদ্ধতিটি তৈরি করা কি আরও বুদ্ধিমান হবে না? যে পদ্ধতিটি ওভাররাইড করে সে কীভাবে জানতে পারে যে পদ্ধতিটি এইভাবে ডিজাইন করা হয়েছিল?
স্পটড

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

আমি আপনার দৃষ্টিকোণটি বুঝতে পেরেছি, তবুও আমি মনে করি এটি বিপজ্জনক যে এক বিকাশকারীকে কেবল কোনও পদ্ধতিকে ওভারড্রইন করা যায় তা জানতে ডকটি পড়া কারণ: 1) যদি এটি ওভাররাইড করা উচিত তবে আমার কোনও গ্যারান্টি নেই সম্পন্ন হবে. 2) যদি এটি ওভাররাইড করা না হয়, তবে কেউ তার সুবিধার জন্য এটি করবে 3) সকলেই ডকটি পড়ে না। এছাড়াও, আমি কখনই কোনও মামলার মুখোমুখি হইনি যেখানে আমার পুরো পদ্ধতিটি ওভাররাইড করা প্রয়োজন, তবে কেবলমাত্র অংশগুলি (এবং আমি একটি টেম্পলেট প্যাটার্ন ব্যবহার করে শেষ করেছি)।
চিতল

@Spotted, 1) যদি আবশ্যক ওভাররাইড করা যেতে, এটি হওয়া উচিত abstract; তবে এমন অনেকগুলি মামলা রয়েছে যেখানে এটি হওয়ার দরকার নেই। 2) যদি এটি ওভাররাইড করা না হয় তবে এটি হওয়া উচিত final(অ-ভার্চুয়াল)। তবে এখনও অনেকগুলি ক্ষেত্রে রয়েছে যেখানে পদ্ধতিগুলি ওভাররাইড করা হতে পারে। 3) যদি ডাউনস্ট্রিম বিকাশকারী ডক্সটি না পড়েন তবে তারা নিজেরাই পায়ে গুলি চালাতে চলেছে, তবে তারা যে পদক্ষেপ গ্রহণ করবে তা বিবেচনা করেই তারা তা করতে চলেছে।
জান হুডেক

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

3

প্রথমত, আমি কেবল উল্লেখ করতে পারি যে এই প্রশ্নটি কেবল নির্দিষ্ট টাইপিং সিস্টেমে প্রযোজ্য। উদাহরণস্বরূপ, কাঠামোগত টাইপিং এবং হাঁসের টাইপিং সিস্টেম - একটি বর্গ কেবল থাকার একই নামের & সঙ্গে একটি পদ্ধতি স্বাক্ষর হবে মানে যে শ্রেণী ছিল সামঞ্জস্যপূর্ণ টাইপ (সেই নির্দিষ্ট পদ্ধতির জন্য অন্তত হাঁসের টাইপিং ক্ষেত্রে)।

এটি (স্পষ্টতই) স্ট্যাটিকালি টাইপ করা ভাষার যেমন জাভা, সি ++ ইত্যাদির ক্ষেত্রের থেকে খুব আলাদা , পাশাপাশি জাভা এবং সি ++, পাশাপাশি সি # এবং অন্যান্য উভয় ক্ষেত্রেই ব্যবহৃত হয় স্ট্রং টাইপিংয়ের প্রকৃতি ।


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

একটি API বা গ্রন্থাগার একটি কংক্রিট পদ্ধতি যা এই ভাষায় পরিকল্পিত হয়ে থাকে হয় overridable, তাহলে এটি (অন্তত আবশ্যক কিছু জানার ক্ষেত্রে (গুলি)) এটি উপেক্ষা করা হতে পারে। অতএব, একটি সিসিল / ভার্চুয়াল / finalকংক্রিটের পদ্ধতিতে ওভাররাইড করা কোনও কোডের গন্ধ নয় ।     (এটি অবশ্যই ধরে নিয়েছে যে এপিআইয়ের ডিজাইনাররা কনভেনশনগুলি অনুসরণ করছেন এবং হয় virtual(সি #) হিসাবে চিহ্নিত করছেন, বা final(জাভা) হিসাবে তারা কী ডিজাইন করছেন তার উপযুক্ত পদ্ধতিগুলি চিহ্নিত করছে ))


আরো দেখুন


হাঁসের টাইপিংয়ে, দুটি শ্রেণীর ক্ষেত্রে কি একই ধরণের স্বাক্ষরযুক্ত টাইপ সামঞ্জস্যপূর্ণ হওয়ার পক্ষে যথেষ্ট, বা পদ্ধতিগুলি একই রকম শব্দার্থক থাকতে হবে, যেমন লিসকভ কিছু বিভক্ত বেস শ্রেণীর পরিবর্তে স্থান পরিবর্তনযোগ্য?
ওয়েইন কনরাড

2

হ্যাঁ কারণ এটি সুপার অ্যান্টি-প্যাটার্নকে কল করতে পারে । এটি পদ্ধতির প্রাথমিক উদ্দেশ্যটিকে অস্বীকার করতে পারে, পার্শ্ব-প্রতিক্রিয়াগুলি (=> বাগগুলি) প্রবর্তন করতে পারে এবং পরীক্ষাগুলিকে ব্যর্থ করে তোলে। আপনি কোন শ্রেণিটি ব্যবহার করবেন কোন ইউনিট পরীক্ষাগুলি লাল (ভরাট) রয়েছে? আমি করব না।

আমি বলে এমনকি আরও যাবেন, যখন একটি পদ্ধতি নয় প্রাথমিক কোড গন্ধ abstractকিংবা final। কারণ এটি একটি নির্মিত সত্তার আচরণকে (ওভাররাইড করে) পরিবর্তন করতে দেয় (এই আচরণটি হারিয়ে যেতে পারে বা পরিবর্তিত হতে পারে)। সাথে abstractএবং finalউদ্দেশ্যটি দ্ব্যর্থহীন:

  • বিমূর্ত: আপনাকে অবশ্যই একটি আচরণ সরবরাহ করতে হবে
  • ফাইনাল: আপনি করছেন না আচরণ সংশোধন করার অনুমতি দেওয়া

কোনও বিদ্যমান শ্রেণীর সাথে আচরণ যুক্ত করার নিরাপদতম উপায়টি আপনার শেষ উদাহরণটি দেখায়: ডেকোরেটার প্যাটার্নটি ব্যবহার করে।

public interface A{
    void a();
}

public final class ConcreteA implements A{
    public void a() {
        ...
    }
}

public final class B implements A{
    private final ConcreteA concreteA;
    public void a(){
        //Additionnal behaviour
        concreteA.a();
    }
}

9
এই কালো এবং সাদা দৃষ্টিভঙ্গি সত্যিই সমস্ত দরকারী নয়। Object.toString()জাভা সম্পর্কে চিন্তা করুন ... এটি যদি হয় abstract, অনেক ডিফল্ট জিনিস কাজ করবে না, এবং কোড এমনকি কেউ যখন toString()পদ্ধতিটি ওভাররাইড না করে তখন সংকলনও করত না ! এটি যদি হয় তবে finalজিনিসগুলি আরও খারাপ হতে পারে - জাভা উপায় ব্যতীত কোনও বিষয়গুলিকে স্ট্রিংয়ে রূপান্তর করার অনুমতি দেওয়ার ক্ষমতা নেই। হিসাবে @Peter Walser সম্পর্কে 'র উত্তর আলোচনা, ডিফল্ট বাস্তবায়নের (যেমন Object.toString()) হয় গুরুত্বপূর্ণ। বিশেষত জাভা 8 ডিফল্ট পদ্ধতিতে।
টেরোসোরাসগুলি

@ টারসোসোরাস আপনি ঠিকই বলেছেন, যদি toString()হয় abstractবা হয় তবে finalএটি ব্যথা হত। আমার ব্যক্তিগত মতামতটি এই পদ্ধতিটি নষ্ট হয়ে গেছে এবং এটি আদৌ না করাই ভাল হত ( সমান এবং হ্যাশকোডের মতো )। জাভা ডিফল্টগুলির প্রাথমিক উদ্দেশ্য হ'ল retrocompatibility সহ API বিবর্তনকে মঞ্জুরি দেওয়া।
চিতল

"রেট্রোকম্প্যাটিবিলিটি" শব্দটির শব্দাবলীর একটি প্রচুর শব্দ রয়েছে।
ক্রেগ

@ স্পটেড এই সাইটে কংক্রিটের উত্তরাধিকারের সাধারণ গ্রহণযোগ্যতায় আমি খুব হতাশ, আমি আরও ভাল প্রত্যাশা করেছি: / আপনার উত্তরের আরও অনেকগুলি
উত্সাহ

1
@ দ্য গেটসহিস্পেরার আমি সম্মত, তবে অন্যদিকে কংক্রিটের উত্তরাধিকারের উপর সজ্জা ব্যবহারের সাবটলগুলি কীভাবে পাওয়া যায় তা আবিষ্কার করতে আমি এত দীর্ঘ সময় নিয়েছি (আসলে আমি যখন পরীক্ষা শুরু করতে শুরু করেছিলাম তখন পরিষ্কার হয়ে গেছে) যে আপনি এর জন্য কাউকে দোষ দিতে পারবেন না । করণীয় হ'ল সর্বোত্তম কাজটি হ'ল অন্যকে শিক্ষিত করার চেষ্টা করা যতক্ষণ না তারা সত্য (রসিকতা) আবিষ্কার করে । :)
স্পটড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.