সি # তে অপরিবর্তনীয় বস্তুর মধ্যে একটি বিজ্ঞপ্তি রেফারেন্স কীভাবে মডেল করবেন?


24

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

public sealed class Room
{
    public Room(string name, Room northExit, Room southExit, Room eastExit, Room westExit)
    {
        this.Name = name;
        this.North = northExit;
        this.South = southExit;
        this.East = eastExit;
        this.West = westExit;
    }

    public string Name { get; }

    public Room North { get; }

    public Room South { get; }

    public Room East { get; }

    public Room West { get; }
}

সুতরাং আমরা দেখতে পাই, এই শ্রেণিটি একটি প্রতিবিম্বিত বিজ্ঞপ্তি সংক্রান্ত রেফারেন্স সহ ডিজাইন করা হয়েছে। তবে শ্রেণিটি অপরিবর্তনীয় বলে আমি 'মুরগী ​​বা ডিম' সমস্যার সাথে আটকে আছি। আমি নিশ্চিত যে অভিজ্ঞ ফাংশনাল প্রোগ্রামাররা জানেন যে এটি কীভাবে কাজ করে। এটি সি # তে কীভাবে পরিচালনা করা যায়?

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

হালনাগাদ:

অলস সূচনা সংক্রান্ত মাইক নাকিসের উত্তরের উপর ভিত্তি করে এখানে একটি কার্যকরী বাস্তবায়ন রয়েছে:

using System;

public sealed class Room
{
    private readonly Func<Room> north;
    private readonly Func<Room> south;
    private readonly Func<Room> east;
    private readonly Func<Room> west;

    public Room(
        string name, 
        Func<Room> northExit = null, 
        Func<Room> southExit = null, 
        Func<Room> eastExit = null, 
        Func<Room> westExit = null)
    {
        this.Name = name;

        var dummyDelegate = new Func<Room>(() => { return null; });

        this.north = northExit ?? dummyDelegate;
        this.south = southExit ?? dummyDelegate;
        this.east = eastExit ?? dummyDelegate;
        this.west = westExit ?? dummyDelegate;
    }

    public string Name { get; }

    public override string ToString()
    {
        return this.Name;
    }

    public Room North
    {
        get { return this.north(); }
    }

    public Room South
    {
        get { return this.south(); }
    }

    public Room East
    {
        get { return this.east(); }
    }

    public Room West
    {
        get { return this.west(); }
    }        

    public static void Main(string[] args)
    {
        Room kitchen = null;
        Room library = null;

        kitchen = new Room(
            name: "Kitchen",
            northExit: () => library
         );

        library = new Room(
            name: "Library",
            southExit: () => kitchen
         );

        Console.WriteLine(
            $"The {kitchen} has a northen exit that " +
            $"leads to the {kitchen.North}.");

        Console.WriteLine(
            $"The {library} has a southern exit that " +
            $"leads to the {library.South}.");

        Console.ReadKey();
    }
}

এটি কনফিগারেশন এবং বিল্ডার প্যাটার্নের জন্য ভাল ক্ষেত্রে মনে হয় feels
গ্রেগ বার্গার্ট

আমি আরও ভাবছি যে কোনও ঘরটি কোনও স্তর বা পর্যায়ের বিন্যাস থেকে ডিক্লুপ করা উচিত, যাতে প্রতিটি ঘর অন্যদের সম্পর্কে জানতে না পারে।
গ্রেগ বার্গার্ট

1
@ রক অ্যান্থনি জনসনকে আমি সত্যিই এই প্রতিচ্ছবি বলি না, তবে এটি প্রাসঙ্গিক নয়। যদিও কেন এটি সমস্যা? এটি অত্যন্ত সাধারণ। আসলে, প্রায় সমস্ত ডেটা স্ট্রাকচার এটি কীভাবে নির্মিত হয়। একটি লিঙ্কযুক্ত তালিকা বা বাইনারি গাছ সম্পর্কে চিন্তা করুন। এগুলি সমস্ত পুনরাবৃত্ত তথ্য স্ট্রাকচার এবং আপনার Roomউদাহরণও।
বাগান মাথা

2
@ রক অ্যান্থনি জনসন অপ্রয়োজনীয় ডেটা স্ট্রাকচারগুলি কমপক্ষে কার্যকরী প্রোগ্রামিংয়ে অত্যন্ত সাধারণ। এই আপনি কিভাবে যুক্ত তালিকা সংজ্ঞায়িত হয়: type List a = Nil | Cons of a * List a। আর একটি বাইনারি ট্রি: type Tree a = Leaf a | Cons of Tree a * Tree a। যেমন আপনি দেখতে পাচ্ছেন, তারা উভয় স্ব-রেফারেন্সিয়াল (পুনরাবৃত্ত)। এখানে আপনি কিভাবে আপনার রুম সংজ্ঞায়িত চাই আছে: type Room = Nil | Open of {name: string, south: Room, east: Room, north: Room, west: Room}
বাগান মাথা

1
আপনি যদি আগ্রহী হন তবে হাসকল বা ওক্যামল শিখতে সময় নিন; এটি আপনার মনের প্রসার ঘটাবে;) এও মনে রাখবেন যে ডেটা স্ট্রাকচার এবং "ব্যবসায়িক বিষয়গুলি" এর মধ্যে কোনও স্পষ্ট সীমানা নেই। উপরে বর্ণিত হাস্কেলটিতে আপনার Roomশ্রেণির সংজ্ঞা এবং কটির মিল রয়েছে তা দেখুন List
বাগান মাথা

উত্তর:


10

স্পষ্টতই, আপনি পোস্ট করেছেন ঠিক কোডটি ব্যবহার করে আপনি এটি করতে পারবেন না, কারণ এক পর্যায়ে আপনাকে এমন একটি বস্তু তৈরি করতে হবে যা অন্য কোনও অবজেক্টের সাথে সংযুক্ত হওয়া দরকার যা এখনও নির্মিত হয়নি।

এটি করার জন্য আমি দুটি উপায় ভাবতে পারি (যা আমি আগে ব্যবহার করেছি):

দুটি পর্যায় ব্যবহার করা হচ্ছে

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

রিলেশনাল ডাটাবেসগুলি মডেলিং করার সময় আপনি ঠিক একই ধরণের সমস্যাটি দেখতে পাবেন: এক টেবিলের একটি বিদেশী কী রয়েছে যা অন্য টেবিলের দিকে নির্দেশ করে এবং অন্য টেবিলটিতে একটি বিদেশী কী থাকতে পারে যা প্রথম টেবিলের দিকে নির্দেশ করে। রিলেশনাল ডেটাবেজে যেভাবে এটি পরিচালনা করা হয় তা হ'ল বিদেশী কী বাধাগুলি (এবং সাধারণত হয়) অতিরিক্ত ALTER TABLE ADD FOREIGN KEYবিবৃতি দিয়ে নির্দিষ্ট করতে পারে যা CREATE TABLEবিবৃতি থেকে পৃথক । সুতরাং, প্রথমে আপনি আপনার সমস্ত সারণী তৈরি করুন, তারপরে আপনি আপনার বিদেশী কী সীমাবদ্ধতা যুক্ত করুন।

রিলেশনাল ডাটাবেসগুলির মধ্যে পার্থক্য এবং আপনি যা করতে চান তা হ'ল রিলেশনাল ডাটাবেসগুলি ALTER TABLE ADD/DROP FOREIGN KEYটেবিলগুলির সারাজীবন ধরে বিবৃতিগুলিকে মঞ্জুর করে চলেছে , আপনি সম্ভবত একটি 'আইএএমআইএমটিভেবল' পতাকা নির্ধারণ করবেন এবং সমস্ত নির্ভরতা উপলব্ধি হয়ে গেলে আরও কোনও রূপান্তর প্রত্যাখ্যান করবেন।

অলস সূচনা ব্যবহার করা

নির্ভরতার রেফারেন্সের পরিবর্তে আপনি একটি প্রতিনিধি পাস করেন যা প্রয়োজনের সময় নির্ভরতার রেফারেন্সটি ফিরিয়ে দেবে। নির্ভরতা আনার পরে, প্রতিনিধিটিকে আর কখনও প্রার্থনা করা হবে না।

প্রতিনিধি সাধারণত একটি ল্যাম্বডা এক্সপ্রেশন রূপ ধারণ করবে, সুতরাং এটি নির্মাণকারীদের উপর নির্ভরতা পাস করার চেয়ে কিছুটা বেশি ভারবস দেখাবে।

এই কৌশলের (ক্ষুদ্রতম) দিকটি হ'ল আপনাকে প্রতিনিধিদের কাছে পয়েন্টার সংরক্ষণের জন্য প্রয়োজনীয় স্টোরেজ স্পেসটি নষ্ট করতে হবে যা কেবলমাত্র আপনার অবজেক্ট গ্রাফের সূচনা করার সময় ব্যবহৃত হবে।

এমনকি আপনি একটি জেনেরিক "অলস রেফারেন্স" শ্রেণি তৈরি করতে পারেন যা এটি প্রয়োগ করে যাতে আপনার প্রতিটি সদস্যের জন্য এটি পুনরায় প্রয়োগ করতে না হয়।

এখানে জাভাতে লেখা এমন শ্রেণি রয়েছে, আপনি সহজেই এটি সি # তে প্রতিলিপি করতে পারেন

(আমার মতামত # সি Function<T>এর Func<T>প্রতিনিধি)

package saganaki.util;

import java.util.Objects;

/**
 * A {@link Function} decorator which invokes the given {@link Function} only once, when actually needed, and then caches its result and never calls it again.
 * It behaves as if it is immutable, which includes the fact that it is thread-safe, provided that the given {@link Function} is also thread-safe.
 *
 * @param <T> the type of object supplied.
 */
public final class LazyImmutable<T> implements Function<T>
{
    private static final boolean USE_DOUBLE_CHECK = false; //TODO try with "double check"
    private final Object lock = new Object();
    @SuppressWarnings( "FieldAccessedSynchronizedAndUnsynchronized" )
    private Function<T> supplier;
    @SuppressWarnings( "FieldAccessedSynchronizedAndUnsynchronized" )
    private T value;

    /**
     * Constructor.
     *
     * @param supplier the {@link Function} which will supply the supplied object the first time it is needed.
     */
    public LazyImmutable( Function<T> supplier )
    {
        assert supplier != null;
        assert !(supplier instanceof LazyImmutable);
        this.supplier = supplier;
        value = null;
    }

    @Override
    public T invoke()
    {
        if( USE_DOUBLE_CHECK )
        {
            if( supplier != null )
                doCheck();
            return value;
        }

        doCheck();
        return value;
    }

    private void doCheck()
    {
        synchronized( lock )
        {
            if( supplier != null )
            {
                value = supplier.invoke();
                supplier = null;
            }
        }
    }

    @Override
    public String toString()
    {
        if( supplier != null )
            return "(lazy)";
        return Objects.toString( value );
    }
}

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


1
মাইক, আপনি মেধাবী অলস সূচনা সম্পর্কে আপনি যা পোস্ট করেছেন তার উপর ভিত্তি করে একটি বাস্তবায়ন অন্তর্ভুক্ত করার জন্য আমি মূল পোস্টটি আপডেট করেছি updated
রক অ্যান্টনি জনসন

1
। নেট লাইব্রেরিটি একটি অলস রেফারেন্স সরবরাহ করে, যথাযথভাবে অলস <T> নাম দেওয়া হয়েছে। কি চমৎকার! আমি কোডরেভিউ.স্ট্যাকেক্সেঞ্জার
রক অ্যান্টনি জনসন

16

মাইক নাকিসের উত্তরের আলস্য সূচনাটি দুটি বস্তুর মধ্যে এক-সময় সূচনা করার জন্য ঠিক সূক্ষ্মভাবে কাজ করে তবে ঘন ঘন আপডেটের সাথে একাধিক আন্ত-সম্পর্কিত বস্তুর জন্য অনর্থক হয়ে যায়।

এটা তোলে কক্ষ মধ্যে লিঙ্ক রাখার অনেক সহজ এবং সামলানো সম্ভব বাহিরে রুম নিজেদের বস্তু একটি ভালো কিছু এ, ImmutableDictionary<Tuple<int, int>, Room>। এইভাবে, বিজ্ঞপ্তি রেফারেন্স তৈরির পরিবর্তে, আপনি কেবলমাত্র এই অভিধানটিতে একটি একক, সহজেই আপডেটযোগ্য, একমুখী রেফারেন্স যুক্ত করছেন।


মনে রাখবেন অপরিবর্তনীয় জিনিসগুলির বিষয়ে কথা বলছিলেন, তাই কোনও আপডেট নেই।
রক অ্যান্টনি জনসন

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

কার্ল, আমাকে ক্ষমা করুন। আমি এখনও কার্যনির্বাহী নূন্যতম, হা হা
রক অ্যান্টনি জনসন

2
এটি সঠিক উত্তর। বিজ্ঞপ্তি নির্ভরতাগুলি সাধারণভাবে ভেঙে তৃতীয় পক্ষের কাছে অর্পণ করা উচিত। পরিবর্তনযোগ্য অবজেক্টের একটি জটিল বিল্ড অ্যান্ড ফ্রিজ সিস্টেমের প্রোগ্রামিংয়ের চেয়ে এটি অনেক সহজ।
বেনিয়ামিন হজসন

ইচ্ছে করে আমি এটিকে আরও +1 দিতে পারতাম ... অপরিবর্তনীয় বা না, "বাহ্যিক" সংগ্রহস্থল বা সূচক (বা যাই হোক না কেন ), এই সমস্ত কক্ষগুলি সঠিকভাবে আঁকানো বেশ অযথা জটিল হবে। আর এই নিষিদ্ধ না Roomথেকে প্রকাশমান সেই সম্পর্ক আছে; তবে, তাদের এমন সূত্র হতে হবে যা সূচক থেকে সহজভাবে পড়ে।
এসভিডজেন

12

ক্রিয়ামূলক শৈলীতে এটি করার উপায় হ'ল আপনি আসলে কী তৈরি করছেন তা স্বীকৃতি: লেবেলযুক্ত প্রান্ত সহ একটি নির্দেশিত গ্রাফ।

Room library = new Room("Library");
Room ballroom = new Room("Ballroom");
Thing chest = new Thing("Treasure chest");
Thing book = new Thing("Ancient Tome");
Dungeon dungeon = Dungeon.Empty
  .WithRoom(library)
  .WithRoom(ballroom)
  .WithThing(chest)
  .WithThing(book)
  .WithPassage("North", library, ballroom)
  .WithPassage("South", ballroom, library)
  .WithContainment(library, chest)
  .WithContainment(chest, book);

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


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

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

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

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

3

চিকেন এবং একটি ডিম ঠিক আছে। এটি সি # তে কোনও মানে করে না:

A a = new A(b);
B b = new B(a);

তবে এটি করে:

A a = new A();
B b = new B(a);
a.setB(b);

তবে তার মানে A অচল নয়!

আপনি প্রতারণা করতে পারেন:

C c = new C();
A a = new A(c);
B b = new B(c);
c.addA(a);
c.addB(b);

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

জমাট বাঁধা নামে একটি প্যাটার্ন রয়েছে:

A a = new A();
B b = new B(a);
a.addB(b);
a.freeze();

এখন 'এ' অপরিবর্তনীয়। 'এ' নয় 'এ' হয়। ঠিক আছে কেন? এতক্ষণ যতক্ষণ না 'এ' জমে যাওয়ার আগে আর কিছুই জানে না, কে চিন্তা করে?

একটি গলানো () পদ্ধতি আছে তবে এটি কখনও 'ক' পরিবর্তন করে না। এটি 'এ' এর একটি পরিবর্তনীয় অনুলিপি তৈরি করে যা আপডেট করা যেতে পারে এবং পাশাপাশি হিমায়িত করা যেতে পারে।

এই পদ্ধতির খারাপ দিকটি হচ্ছে শ্রেণিটি অপরিবর্তনীয়তা প্রয়োগ করছে না। নিম্নলিখিত পদ্ধতিটি হ'ল এটি টাইপ থেকে স্থিতিশীল কিনা তা আপনি বলতে পারবেন না।

এই সমস্যাটি সমাধান করার জন্য আমি আসলেই সি # তে জানি না। আমি সমস্যাগুলি লুকানোর উপায় জানি। কখনও কখনও যথেষ্ট।

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


আমাকে নতুন প্যাটার্নে পরিচয় করানোর জন্য +1। প্রথমে আমি কখনই হিমশীতল হওয়ার কথা শুনেছি।
রক অ্যান্টনি জনসন

a.freeze()ImmutableAটাইপ ফিরে আসতে পারে । যা এটি মূলত বিল্ডার প্যাটার্নকে তৈরি করে।
ব্রায়ান চেন

@ ব্রায়ানচেন আপনি যদি তা করেন তবে bপুরানো মিউটটেবলের একটি রেফারেন্স রেখেই যান a। ধারণাটি হ'ল a এবং bসিস্টেমের বাকী অংশে ছেড়ে দেওয়ার আগে একে অপরের অপরিবর্তনীয় সংস্করণগুলিকে নির্দেশ করা উচিত।
candied_orange

@ রক অ্যান্থনি জনসন এটিই এরিক লিপার্টকে পপসিকল অপরিবর্তনীয়তা বলেছিলেন ।
স্পটড

1

কিছু স্মার্ট ব্যক্তি ইতিমধ্যে এটি সম্পর্কে তাদের মতামত জানিয়েছিল, তবে আমি কেবল মনে করি যে প্রতিবেশীরা কী তা জানার ঘরের দায়িত্ব নয়।

আমি মনে করি যে কক্ষগুলি কোথায় আছে তা জানা ভবনটির দায়িত্ব। ঘরে যদি সত্যিই এটির প্রয়োজন হয় তবে প্রতিবেশীরা এটিতে আইএনইগবার ফাইন্ডারটি পাস করুন।

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