অ্যান্ড্রয়েডে নির্ভরতা ইনজেকশন

ডিপেনডেন্সি ইনজেকশন (DI) হল একটি কৌশল যা প্রোগ্রামিংয়ে ব্যাপকভাবে ব্যবহৃত হয় এবং অ্যান্ড্রয়েড ডেভেলপমেন্টের জন্য উপযুক্ত। DI এর নীতিগুলি অনুসরণ করে, আপনি ভাল অ্যাপ আর্কিটেকচারের ভিত্তি স্থাপন করেন।

নির্ভরতা ইনজেকশন প্রয়োগ করা আপনাকে নিম্নলিখিত সুবিধা প্রদান করে:

  • কোডের পুনরায় ব্যবহারযোগ্যতা
  • রিফ্যাক্টরিংয়ের সহজলভ্যতা
  • পরীক্ষার সহজতা

নির্ভরতা ইনজেকশনের মৌলিক বিষয়

বিশেষত Android-এ নির্ভরতা ইনজেকশন কভার করার আগে, এই পৃষ্ঠাটি নির্ভরতা ইনজেকশন কীভাবে কাজ করে তার আরও সাধারণ ওভারভিউ প্রদান করে।

নির্ভরতা ইনজেকশন কি?

ক্লাসের জন্য প্রায়ই অন্যান্য ক্লাসের রেফারেন্সের প্রয়োজন হয়। উদাহরণস্বরূপ, একটি Car ক্লাস একটি Engine শ্রেণীর একটি রেফারেন্স প্রয়োজন হতে পারে. এই প্রয়োজনীয় শ্রেণীগুলিকে বলা হয় নির্ভরশীলতা , এবং এই উদাহরণে Car ক্লাস চালানোর জন্য Engine ক্লাসের একটি উদাহরণ থাকার উপর নির্ভরশীল।

একটি ক্লাসের জন্য প্রয়োজনীয় একটি বস্তু পেতে তিনটি উপায় রয়েছে:

  1. শ্রেণী তার প্রয়োজনীয় নির্ভরতা তৈরি করে। উপরের উদাহরণে, Car তার নিজস্ব Engine উদাহরণ তৈরি করবে এবং শুরু করবে।
  2. অন্য কোথাও থেকে এটি ধরুন। কিছু Android API, যেমন Context getters এবং getSystemService() , এইভাবে কাজ করে।
  3. এটি একটি পরামিতি হিসাবে সরবরাহ করুন. অ্যাপটি এই নির্ভরতাগুলি প্রদান করতে পারে যখন ক্লাসটি তৈরি করা হয় বা প্রতিটি নির্ভরতা প্রয়োজন এমন ফাংশনে তাদের পাস করে। উপরের উদাহরণে, Car কনস্ট্রাক্টর একটি প্যারামিটার হিসাবে Engine গ্রহণ করবে।

তৃতীয় বিকল্প নির্ভরতা ইনজেকশন! এই পদ্ধতির সাহায্যে আপনি একটি শ্রেণীর নির্ভরতা গ্রহণ করেন এবং ক্লাসের দৃষ্টান্ত সেগুলি নিজেই প্রাপ্ত করার পরিবর্তে তাদের প্রদান করেন।

এখানে একটি উদাহরণ. নির্ভরতা ইনজেকশন ছাড়াই, এমন একটি Car প্রতিনিধিত্ব করা যা কোডে নিজস্ব Engine নির্ভরতা তৈরি করে:

কোটলিন

class Car {

    private val engine = Engine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

জাভা

class Car {

    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}
নির্ভরতা ইনজেকশন ছাড়া গাড়ী ক্লাস

এটি নির্ভরতা ইনজেকশনের একটি উদাহরণ নয় কারণ Car ক্লাস তার নিজস্ব Engine তৈরি করছে। এটি সমস্যাযুক্ত হতে পারে কারণ:

  • Car এবং Engine দৃঢ়ভাবে সংযুক্ত - Car একটি উদাহরণ এক ধরনের Engine ব্যবহার করে, এবং কোন উপশ্রেণী বা বিকল্প বাস্তবায়ন সহজে ব্যবহার করা যায় না। যদি Car তার নিজস্ব Engine তৈরি করতে চায়, তাহলে আপনাকে Gas এবং Electric ধরনের ইঞ্জিনের জন্য একই Car পুনরায় ব্যবহার না করে দুই ধরনের Car তৈরি করতে হবে।

  • Engine উপর কঠিন নির্ভরতা পরীক্ষাকে আরও কঠিন করে তোলে। Car Engine একটি বাস্তব উদাহরণ ব্যবহার করে, এইভাবে আপনাকে বিভিন্ন পরীক্ষার ক্ষেত্রে Engine পরিবর্তন করতে একটি টেস্ট ডাবল ব্যবহার করা থেকে বাধা দেয়।

নির্ভরতা ইনজেকশনের সাথে কোডটি কেমন দেখাচ্ছে? প্রারম্ভিকতার সময় Car নিজস্ব Engine অবজেক্ট তৈরি করার প্রতিটি উদাহরণের পরিবর্তে, এটি তার কনস্ট্রাক্টরে একটি প্যারামিটার হিসাবে একটি Engine অবজেক্ট গ্রহণ করে:

কোটলিন

class Car(private val engine: Engine) {
    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val engine = Engine()
    val car = Car(engine)
    car.start()
}

জাভা

class Car {

    private final Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Car car = new Car(engine);
        car.start();
    }
}
নির্ভরতা ইনজেকশন ব্যবহার করে গাড়ি ক্লাস

main ফাংশন Car ব্যবহার করে। কারণ Car Engine উপর নির্ভর করে, অ্যাপটি Engine একটি দৃষ্টান্ত তৈরি করে এবং তারপরে এটি ব্যবহার করে Car একটি উদাহরণ তৈরি করে। এই DI-ভিত্তিক পদ্ধতির সুবিধাগুলি হল:

  • Car পুনর্ব্যবহারযোগ্যতা। আপনি Car থেকে Engine বিভিন্ন বাস্তবায়নে পাস করতে পারেন। উদাহরণস্বরূপ, আপনি ElectricEngine নামক Engine একটি নতুন সাবক্লাস সংজ্ঞায়িত করতে পারেন যা আপনি Car ব্যবহার করতে চান। আপনি যদি DI ব্যবহার করেন, তবে আপনাকে যা করতে হবে তা হল আপডেট হওয়া ElectricEngine সাবক্লাসের একটি উদাহরণে পাস করা, এবং Car এখনও কোনো পরিবর্তন ছাড়াই কাজ করে।

  • Car সহজ পরীক্ষা। আপনার বিভিন্ন পরিস্থিতিতে পরীক্ষা করার জন্য আপনি টেস্ট ডাবলে পাস করতে পারেন। উদাহরণস্বরূপ, আপনি FakeEngine নামক Engine একটি টেস্ট ডবল তৈরি করতে পারেন এবং বিভিন্ন পরীক্ষার জন্য এটি কনফিগার করতে পারেন।

অ্যান্ড্রয়েডে নির্ভরতা ইনজেকশন করার দুটি প্রধান উপায় রয়েছে:

  • কনস্ট্রাক্টর ইনজেকশন । এটি উপরে বর্ণিত উপায়। আপনি একটি ক্লাসের নির্ভরতা তার কনস্ট্রাক্টরের কাছে পাস করেন।

  • ফিল্ড ইনজেকশন (বা সেটার ইনজেকশন) । কিছু কিছু অ্যান্ড্রয়েড ফ্রেমওয়ার্ক ক্লাস যেমন অ্যাক্টিভিটি এবং ফ্র্যাগমেন্টগুলি সিস্টেম দ্বারা তাত্ক্ষণিক করা হয়, তাই কনস্ট্রাক্টর ইনজেকশন সম্ভব নয়৷ ফিল্ড ইনজেকশনের সাহায্যে, ক্লাস তৈরি হওয়ার পরে নির্ভরতাগুলি তাত্ক্ষণিক হয়। কোড এই মত দেখাবে:

কোটলিন

class Car {
    lateinit var engine: Engine

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.engine = Engine()
    car.start()
}

জাভা

class Car {

    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.setEngine(new Engine());
        car.start();
    }
}

স্বয়ংক্রিয় নির্ভরতা ইনজেকশন

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

  • বড় অ্যাপ্লিকেশানগুলির জন্য, সমস্ত নির্ভরতা গ্রহণ এবং সঠিকভাবে সংযোগ করার জন্য প্রচুর পরিমাণে বয়লারপ্লেট কোডের প্রয়োজন হতে পারে। একটি বহু-স্তরযুক্ত আর্কিটেকচারে, একটি শীর্ষ স্তরের জন্য একটি বস্তু তৈরি করার জন্য, আপনাকে এটির নীচের স্তরগুলির সমস্ত নির্ভরতা প্রদান করতে হবে। একটি কংক্রিট উদাহরণ হিসাবে, একটি বাস্তব গাড়ি তৈরি করতে আপনার একটি ইঞ্জিন, একটি ট্রান্সমিশন, একটি চ্যাসিস এবং অন্যান্য অংশের প্রয়োজন হতে পারে; এবং একটি ইঞ্জিনের জন্য সিলিন্ডার এবং স্পার্ক প্লাগ প্রয়োজন।

  • যখন আপনি নির্ভরতাগুলিকে পাস করার আগে তৈরি করতে সক্ষম না হন - উদাহরণস্বরূপ যখন আপনার অ্যাপের প্রবাহে অলস প্রাথমিককরণ বা স্কোপিং অবজেক্টগুলি ব্যবহার করেন - তখন আপনাকে একটি কাস্টম কন্টেইনার (বা নির্ভরতার গ্রাফ) লিখতে এবং বজায় রাখতে হবে যা আপনার জীবনকাল পরিচালনা করে স্মৃতিতে নির্ভরতা।

এমন লাইব্রেরি রয়েছে যা নির্ভরতা তৈরি এবং প্রদানের প্রক্রিয়া স্বয়ংক্রিয়ভাবে এই সমস্যার সমাধান করে। তারা দুটি বিভাগে মাপসই করা হয়:

  • প্রতিফলন-ভিত্তিক সমাধান যা রানটাইমে নির্ভরতাকে সংযুক্ত করে।

  • স্ট্যাটিক সমাধান যা কম্পাইলের সময় নির্ভরতা সংযোগ করতে কোড তৈরি করে।

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

নির্ভরতা ইনজেকশনের বিকল্প

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

কোটলিন

object ServiceLocator {
    fun getEngine(): Engine = Engine()
}

class Car {
    private val engine = ServiceLocator.getEngine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

জাভা

class ServiceLocator {

    private static ServiceLocator instance = null;

    private ServiceLocator() {}

    public static ServiceLocator getInstance() {
        if (instance == null) {
            synchronized(ServiceLocator.class) {
                instance = new ServiceLocator();
            }
        }
        return instance;
    }

    public Engine getEngine() {
        return new Engine();
    }
}

class Car {

    private Engine engine = ServiceLocator.getInstance().getEngine();

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

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

নির্ভরতা ইনজেকশনের তুলনায়:

  • একটি পরিষেবা লোকেটার দ্বারা প্রয়োজনীয় নির্ভরতার সংগ্রহ কোডটি পরীক্ষা করা কঠিন করে তোলে কারণ সমস্ত পরীক্ষাকে একই গ্লোবাল সার্ভিস লোকেটারের সাথে ইন্টারঅ্যাক্ট করতে হয়।

  • নির্ভরতাগুলি শ্রেণী বাস্তবায়নে এনকোড করা হয়, API পৃষ্ঠে নয়। ফলস্বরূপ, একটি ক্লাসের বাইরে থেকে কী প্রয়োজন তা জানা আরও কঠিন। ফলস্বরূপ, Car পরিবর্তন বা পরিষেবা লোকেটারে উপলব্ধ নির্ভরতাগুলি রেফারেন্সগুলি ব্যর্থ করে রানটাইম বা পরীক্ষার ব্যর্থতার কারণ হতে পারে।

  • আপনি যদি সমগ্র অ্যাপের জীবনকাল ব্যতীত অন্য কিছুতে সুযোগ পেতে চান তবে অবজেক্টের জীবনকাল পরিচালনা করা আরও কঠিন।

আপনার অ্যান্ড্রয়েড অ্যাপে হিল্ট ব্যবহার করুন

হিল্ট হ'ল অ্যান্ড্রয়েডে নির্ভরতা ইনজেকশনের জন্য জেটপ্যাকের প্রস্তাবিত লাইব্রেরি। হিল্ট আপনার প্রোজেক্টের প্রতিটি অ্যান্ড্রয়েড ক্লাসের জন্য কন্টেইনার সরবরাহ করে এবং আপনার জন্য স্বয়ংক্রিয়ভাবে তাদের জীবনচক্র পরিচালনা করে আপনার অ্যাপ্লিকেশনে DI করার একটি আদর্শ উপায় সংজ্ঞায়িত করে।

হিল্ট জনপ্রিয় DI লাইব্রেরি Dagger- এর উপরে তৈরি করা হয়েছে কম্পাইল টাইম শুদ্ধতা, রানটাইম পারফরম্যান্স, স্কেলেবিলিটি, এবং অ্যান্ড্রয়েড স্টুডিও সমর্থন যা Dagger প্রদান করে।

হিল্ট সম্পর্কে আরও জানতে হিল্টের সাথে ডিপেন্ডেন্সি ইনজেকশন দেখুন।

উপসংহার

নির্ভরতা ইনজেকশন আপনার অ্যাপকে নিম্নলিখিত সুবিধাগুলি প্রদান করে:

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

  • রিফ্যাক্টরিংয়ের সহজতা: নির্ভরতাগুলি এপিআই পৃষ্ঠের একটি যাচাইযোগ্য অংশ হয়ে ওঠে, তাই সেগুলি বাস্তবায়নের বিশদ হিসাবে লুকানো না হয়ে অবজেক্ট তৈরির সময় বা কম্পাইলের সময় পরীক্ষা করা যেতে পারে।

  • পরীক্ষার সহজতা: একটি ক্লাস তার নির্ভরতা পরিচালনা করে না, তাই আপনি যখন এটি পরীক্ষা করছেন, আপনি আপনার বিভিন্ন ক্ষেত্রে পরীক্ষা করার জন্য বিভিন্ন বাস্তবায়নে পাস করতে পারেন।

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

অতিরিক্ত সম্পদ

নির্ভরতা ইনজেকশন সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত সংস্থানগুলি দেখুন।

নমুনা