সমষ্টিগুলির মধ্যে রেফারেন্সগুলির বৈধতা কীভাবে আচরণ করবেন?


11

আমি সমষ্টিগুলির মধ্যে রেফারেন্স সহ কিছুটা লড়াই করছি। ধরে নেওয়া যাক সামগ্রিকের সামগ্রিকের Carএকটি রেফারেন্স রয়েছে Driver। এই রেফারেন্স থাকার মাধ্যমে মডেল করা হবে Car.driverId

এখন আমার সমস্যাটি হ'ল আমি একটি Carসামগ্রিক ক্রিয়াকলাপটি বৈধ করতে কতদূর যেতে পারি CarFactory। আমার কি বিশ্বাস করা উচিত যে উত্তীর্ণরা DriverIdকোনও বিদ্যমানকে বোঝায় Driverবা আমার সেই আক্রমণকারীটি পরীক্ষা করা উচিত?

চেক করার জন্য, আমি দুটি সম্ভাবনা দেখতে পাচ্ছি:

  • আমি একটি সম্পূর্ণ ড্রাইভার সত্তা গ্রহণ করতে গাড়ী কারখানার স্বাক্ষর পরিবর্তন করতে পারি। কারখানাটি তখন কেবল সেই সত্তা থেকে আইডিটি বেছে নেবে এবং এটি দিয়ে গাড়িটি তৈরি করবে। এখানে আক্রমণকারী নিখুঁতভাবে চেক করা হয়।
  • আমি স্পষ্টভাবে কল DriverRepositoryমধ্যে একটি রেফারেন্স পেতে পারে ।CarFactorydriverRepository.exists(driverId)

কিন্তু এখন আমি ভাবছি এতটা আক্রমণাত্মক চেকিং কি না? আমি কল্পনা করতে পারি যে এই সমষ্টিগুলি পৃথক সীমানা প্রসঙ্গে থাকতে পারে, এবং এখন আমি গাড়ি বিসিটিকে চালক বিসি-র ড্রাইভার-রিপোসিটোরি বা ড্রাইভার সত্তার উপর নির্ভরতার সাথে দূষিত করব।

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

উত্তর:


6

আমি একটি সম্পূর্ণ ড্রাইভার সত্তা গ্রহণ করতে গাড়ী কারখানার স্বাক্ষর পরিবর্তন করতে পারি। কারখানাটি তখন কেবল সেই সত্তা থেকে আইডিটি বেছে নেবে এবং এটি দিয়ে গাড়িটি তৈরি করবে। এখানে আক্রমণকারী নিখুঁতভাবে চেক করা হয়।

আপনি এই চেকটি নিখরচায় পেয়ে যাওয়ায় এই পদ্ধতির আবেদন আকর্ষণীয় এবং এটি সর্বব্যাপী ভাষার সাথে ভালভাবে সাজানো। ক Carএকটি দ্বারা চালিত হয় না driverId, তবে ক দ্বারা চালিত হয় Driver

এই দৃষ্টিভঙ্গিটি ভন ভার্নন তার পরিচয় ও অ্যাক্সেসের নমুনা সীমিত প্রসঙ্গে ব্যবহার করেছেন যেখানে তিনি একটি Userসমষ্টিতে একটি সমষ্টি পাস করেন Groupতবে Groupএকমাত্র মানটির ধরণে থাকে GroupMember। আপনি দেখতে পাচ্ছেন যে এটি তাকে ব্যবহারকারীর সক্ষমতার জন্যও পরীক্ষা করতে দেয় (আমরা ভালভাবে জানি যে চেকটি বাসি হতে পারে)।

    public void addUser(User aUser) {
        //original code omitted
        this.assertArgumentTrue(aUser.isEnabled(), "User is not enabled.");

        if (this.groupMembers().add(aUser.toGroupMember()) && !this.isInternalGroup()) {
            //original code omitted
        }
    }

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

আপনি যদি ইন্টারফেস বিভাজন নীতি (আইএসপি) প্রয়োগ করতে আসলে ভাল নাম নিয়ে আসতে পারেন তবে আপনি এমন একটি ইন্টারফেসের উপর নির্ভর করতে পারেন যার আচরণগত পদ্ধতি নেই। আপনি সম্ভবত একটি মান অবজেক্ট কনসেপ্ট নিয়ে আসতে পারেন যা একটি অপরিবর্তনীয় ড্রাইভারের রেফারেন্সকে উপস্থাপন করে এবং এটি কেবলমাত্র বিদ্যমান ড্রাইভার (উদাহরণস্বরূপ DriverDescriptor driver = driver.descriptor()) থেকে ইনস্ট্যান্ট করা যেতে পারে can

আমি কল্পনা করতে পারি যে এই সমষ্টিগুলি পৃথক সীমানা প্রসঙ্গে থাকতে পারে, এবং এখন আমি গাড়ি বিসিটিকে চালক বিসি-র ড্রাইভার-রিপোসিটোরি বা ড্রাইভার সত্তার উপর নির্ভরতার সাথে দূষিত করব।

না, আপনি আসলে না। একটি প্রসঙ্গে ধারণাগুলি অন্যের মধ্যে রক্তপাত না করে তা নিশ্চিত করার জন্য সর্বদা একটি দুর্নীতিবিরোধী স্তর থাকে's আপনার গাড়ি চালক সংঘের জন্য উত্সর্গীকৃত বিসি থাকলে এটি আসলে অনেক সহজ কারণ আপনি বিদ্যমান ধারণাগুলির যেমন Carএবং Driverবিশেষত সেই প্রসঙ্গে মডেল করতে পারেন ।

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

মনে রাখবেন যে ওয়েব-পরিষেবাদিগুলি বিসি-র মধ্যে সর্বোত্তম একীকরণের পদ্ধতি নয়। আপনি মেসেজিংয়ের উপরও নির্ভর করতে পারেন যেখানে উদাহরণস্বরূপ UserCreatedড্রাইভার ম্যানেজমেন্ট প্রসঙ্গে কোনও বার্তা একটি প্রত্যন্ত প্রসঙ্গে ব্যবহার করা হবে যা তার নিজস্ব ডিবিতে ড্রাইভারের উপস্থাপনা সংরক্ষণ করবে। DriverLookupServiceতারপর ব্যবহার করতে পারে এই ডিবি এবং ড্রাইভার তথ্য আরও বার্তাগুলি (উদাঃ সঙ্গে আপ টু ডেট রাখা হবে DriverLicenceRevoked)।

আপনার ডোমেনের জন্য কোন পদ্ধতিটি ভাল তা আমি সত্যিই বলতে পারি না তবে আশা করি এটি আপনাকে সিদ্ধান্ত নেওয়ার জন্য যথেষ্ট অন্তর্দৃষ্টি দেবে।


3

আপনি যেভাবে প্রশ্নটি জিজ্ঞাসা করছেন (এবং দুটি বিকল্পের প্রস্তাব দিচ্ছেন) এটি কেবলমাত্র উদ্বেগের কারণ হ'ল গাড়িটি তৈরি হওয়ার সময় ড্রাইভারআইড এখনও বৈধ।

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

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

বিটিডব্লু, আমি @ প্রাইস জোনসের সাথে একমত যে গাড়ি এবং চালকের মধ্যে সংঘটিত সম্ভবত গাড়ি বা ড্রাইভার উভয়ের থেকে পৃথক একটি দায়িত্ব। এই ধরণের সমিতি সময়ের সাথে সাথে কেবল জটিলতায় বৃদ্ধি পাবে কারণ এটি মনে হয় একটি নির্ধারিত সমস্যার মতো (ড্রাইভার, গাড়ি, টাইম স্লট / উইন্ডোজ, বিকল্পগুলি ইত্যাদি ...) এমনকি যদি এটি নিবন্ধকরণ সমস্যার মতো হয় তবেও কেউ historicalতিহাসিক চাইবে নিবন্ধগুলি পাশাপাশি বর্তমান নিবন্ধসমূহ। সুতরাং এটি খুব ভাল নিজের খ্রিস্টপূর্ব সম্পূর্ণ খাঁটি হতে পারে।

বিসি এর মধ্যে বরাদ্দকৃত মোট সংস্থাগুলির বিসি এর মধ্যে বা একটি পৃথক বিসি এর মধ্যে আপনি বরাদ্দ প্রকল্প (যেমন একটি বুলিয়ান বা রেফারেন্স গণনা) সরবরাহ করতে পারেন, বলুন, গাড়ি এবং ড্রাইভারের মধ্যে সমিতি তৈরির জন্য দায়ী একজন। আপনি যদি পূর্বের কাজটি করেন তবে আপনি গাড়ি বা ড্রাইভার বিসি-কে জারি করা (বৈধ) মুছে ফেলা অপারেশনগুলিকে অনুমতি দিতে পারেন; যদি আপনি পরে করেন, আপনার গাড়ি এবং ড্রাইভার বিসি এর থেকে মুছে ফেলা রোধ করতে হবে এবং তার পরিবর্তে গাড়ি এবং ড্রাইভার অ্যাসোসিয়েশন শিডিয়ুলারের মাধ্যমে তাদের প্রেরণ করতে হবে।

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

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


আরও মৌলিক সমাধান হিসাবে, আপনি গাড়ি ও ড্রাইভার বিসি'র মালিকানা গাড়ি / ড্রাইভার অ্যাসোসিয়েশন শিডিয়ুলারের কাছে রেখে কেবলমাত্র endতিহাসিক-রেকর্ড কারখানা হিসাবে বিবেচনা করতে পারেন। বিসি গাড়িটি একটি নতুন গাড়ি তৈরি করতে পারে, তার ভিআইএন সহ গাড়ির সমস্ত বিবরণ দিয়ে সম্পূর্ণ complete গাড়ির মালিকানা গাড়ি / ড্রাইভার অ্যাসোসিয়েশন শিডিউলার দ্বারা পরিচালিত হয়। এমনকি যদি কোনও গাড়ি / ড্রাইভার সমিতি মুছে ফেলা হয়, এবং গাড়িটি নিজেই ধ্বংস হয়ে যায়, তবুও গাড়িটির রেকর্ডগুলি গাড়ি বিসি-তে সংজ্ঞা অনুসারে বিদ্যমান এবং আমরা গাড়ি বিসি ব্যবহার করতে পারি historicalতিহাসিক তথ্য অনুসন্ধান করতে; গাড়ি / ড্রাইভার সমিতি / মালিকানাগুলি (অতীত, বর্তমান এবং সম্ভাব্য ভবিষ্যতের নির্ধারিত) অন্য বিসি দ্বারা পরিচালিত হচ্ছে।


2

আসুন ধরে নেওয়া যাক সামগ্রিক গাড়িটির মোট চালকের একটি উল্লেখ রয়েছে। Car.driverId করে এই রেফারেন্সটি মডেল করা হবে।

হ্যাঁ, এটি একের সাথে অন্য একত্রিত করার সঠিক উপায়।

যদি আমি ডোমেন বিশেষজ্ঞদের সাথে কথা বলি, তারা এ জাতীয় উল্লেখগুলির বৈধতা নিয়ে কখনও প্রশ্ন করবে না

আপনার ডোমেন বিশেষজ্ঞদের জিজ্ঞাসা করার জন্য ঠিক সঠিক প্রশ্ন নয়। "যদি ড্রাইভারটি না থাকে তবে ব্যবসায়ের জন্য কী খরচ হবে?" চেষ্টা করুন?

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

তাই কিছু

class DriverService {
    private final DriverRepository driverRepository;

    boolean doesDriverExist(DriverId driverId) {
        return driverRepository.exists(driverId);
    }
}

আপনি আসলে ড্রাইভারআইড সম্পর্কে ডোমেনটি বিভিন্ন পয়েন্টে জিজ্ঞাসা করেন

  • কমান্ড প্রেরণের আগে ক্লায়েন্টের কাছ থেকে
  • অ্যাপ্লিকেশনটিতে, কমান্ডটি মডেলের কাছে যাওয়ার আগে
  • কমান্ড প্রসেসিংয়ের সময় ডোমেন মডেলের মধ্যে

এই যে কোনও বা সমস্ত চেক ব্যবহারকারী ইনপুটটিতে ত্রুটি হ্রাস করতে পারে। তবে তারা সবাই বাসি ডেটা থেকে কাজ করছে; আমরা প্রশ্ন জিজ্ঞাসা করার সাথে সাথে অন্যান্য সমষ্টিগত পরিবর্তন হতে পারে। সুতরাং সর্বদা মিথ্যা নেতিবাচক / ধনাত্মকতার কিছুটা বিপদ থাকে।

  • একটি ব্যতিক্রম প্রতিবেদনে, কমান্ডটি শেষ হওয়ার পরে চালান

এখানে, আপনি এখনও বাসি ডেটা নিয়ে কাজ করছেন (সমষ্টিগুলি আপনি কমান্ড চালাচ্ছেন যখন আপনি রিপোর্টটি চালাচ্ছেন, আপনি সামগ্রিক সকলের কাছে সাম্প্রতিক লেখাগুলি দেখতে সক্ষম নাও হতে পারেন)। কিন্তু সমষ্টিগুলির মধ্যে থাকা চেকগুলি কখনই নিখুঁত হতে পারে না (Car.create (ড্রাইভার: 7) একই সাথে চালক.ডিলেট (ড্রাইভার: 7) হিসাবে চলছে) সুতরাং এটি আপনাকে ঝুঁকির বিরুদ্ধে প্রতিরক্ষা একটি অতিরিক্ত স্তর দেয়।


1
Driver.deleteঅস্তিত্ব থাকা উচিত নয়। আমি কখনই এমন ডোমেইন দেখিনি যেখানে সমষ্টিগুলি ধ্বংস হয়ে যায়। এআরএসকে চারপাশে রেখে আপনি কখনও এতিমদের সাথে শেষ করতে পারবেন না।
প্ল্লেক্স

1

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

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


আমি গাড়ি / ড্রাইভারের সম্পর্ক সম্পর্কেও ভেবেছিলাম - তবে একটি ড্রাইভারআসাইনমেন্ট সামগ্রিক প্রবর্তন করে যা কেবলমাত্র রেফারেন্সকে বৈধ হওয়া দরকার needs
ভয়েসফুউনরেজন

1

কিন্তু এখন আমি ভাবছি এতটা আক্রমণাত্মক চেকিং কি না?

আমি তাই মনে করি. ডিবি থেকে প্রদত্ত ড্রাইভারআইড আনার সাথে যদি এটি না থাকে তবে একটি খালি সেট দেয়। সুতরাং রিটার্নের ফলাফলটি যাচাই করা এটি জিজ্ঞাসা করে যে এটি বিদ্যমান (এবং তারপরে আনয়ন) অপ্রয়োজনীয়।

তারপরে শ্রেণি নকশা এটি অপ্রয়োজনীয় করে তোলে

  • যদি প্রয়োজন হয় "একটি পার্ক করা গাড়ি চালক থাকতে পারে বা নাও করতে পারে"
  • যদি কোনও ড্রাইভার অবজেক্টের প্রয়োজন DriverIdহয় এবং এটি কনস্ট্রাক্টরে সেট করা থাকে।
  • যদি Carপ্রয়োজন হয় তবে DriverIdএকজন Driver.Idগেটর থাকুন। সেটার নেই।

ব্যবসায়ের নিয়মের জন্য সংগ্রহস্থল স্থান নয়

  • একজন Carখেয়াল যদি এটি একটি হয়েছে Driver(অথবা তার অন্তত আইডি)। Driverএটি আছে যদি একটি যত্নশীল DriverIdRepositoryতথ্য অখণ্ডতা বজায় রাখে এবং ড্রাইভার-কম গাড়ি সম্পর্কে কম গ্রাহ্য না পারে।
  • ডিবিতে ডেটা অখণ্ডতার বিধি থাকবে। নাল নন কী, নাল-সীমাবদ্ধতা ইত্যাদি But তবে ডেটা অখণ্ডতা ডেটা / টেবিল স্কিমার সম্পর্কে, ব্যবসায়িক বিধি নয়। এক্ষেত্রে আমাদের দৃ corre় সম্পর্কযুক্ত, সহাবস্থানীয় সম্পর্ক রয়েছে তবে দুটির সাথে মিশে না।
  • যেটি একটি DriverIdব্যবসায়িক ডোমেন জিনিস তা যথাযথ শ্রেণিতে পরিচালনা করা হয়।

উদ্বেগ লঙ্ঘনের বিচ্ছেদ

... Repository.DriverIdExists()প্রশ্ন জিজ্ঞাসা যখন ঘটে ।

একটি ডোমেন অবজেক্ট তৈরি করুন। যদি না হয় Driverতবে সম্ভবত একটি DriverInfo(কেবল একটি DriverIdএবং Nameবলা যাক) অবজেক্ট। DriverIdনির্মাণ উপরে যাচাই করা হয়। এটি অবশ্যই উপস্থিত থাকতে হবে এবং সঠিক ধরণের এবং অন্য যে কোনও কিছু হতে হবে। তারপরে এটি কোনও ক্লায়েন্ট ক্লাস ডিজাইনের সমস্যাটি কীভাবে অস্তিত্বহীন ড্রাইভার / ড্রাইভারআইডি মোকাবেলা করতে হয়।

Carআপনি কল না করা পর্যন্ত ড্রাইভার ছাড়া ভাল হতে পারে Car.Drive()। কোন ক্ষেত্রে Carঅবশ্যই অবজেক্ট তার নিজস্ব রাষ্ট্রকে নিশ্চিত করে। একটি ছাড়া গাড়ি চালানো যায় না Driver- ভাল, এখনও না।

শ্রেণি থেকে কোনও সম্পত্তি আলাদা করা খারাপ

অবশ্যই, Car.DriverIdযদি আপনি চান একটি আছে । তবে এটির মতো কিছু দেখতে হবে:

public class Car {
    // Non-null driver has a driverId by definition/contract.
    protected DriverInfo myDriver;
    public DriverId {get { return myDriver.Id; }}

    public void Drive() {
       if (myDriver == null ) return errorMessage; // or something
       // ... continue driving
    }
}

এটা না:

public class Car {
    public int DriverId {get; protected set;}
}

এখন Carঅবশ্যই DriverIdবৈধতার সমস্ত সমস্যা নিয়ে কাজ করতে হবে - একক দায়িত্বের নীতি লঙ্ঘন; এবং অনর্থক কোড সম্ভবত।

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