আমি কি encapsulation অতিরিক্ত ব্যবহারে ভুগছি?


11

আমি বিভিন্ন কোডে আমার কোডটিতে এমন কিছু লক্ষ্য করেছি যা দেখে মনে হয় কোডের গন্ধ আমার কাছে লাগে এবং করণীয় খারাপ হয় তবে আমি এটি মোকাবেলা করতে পারি না।

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

এখানে এমন একটি শ্রেণীর উদাহরণ রয়েছে যা একটি .csv ফাইল থেকে কিছু ডেটা পড়ে এবং গ্রাহকদের একটি গ্রুপ প্রদান করে (বিভিন্ন ক্ষেত্র এবং বৈশিষ্ট্য সহ অন্য একটি বস্তু)।

public class GroupOfCustomersImporter {
    //... Call fields ....
    public GroupOfCustomersImporter(String filePath) {
        this.filePath = filePath;
        customers = new HashSet<Customer>();
        createCSVReader();
        read();
        constructTTRP_Instance();
    }

    private void createCSVReader() {
        //....
    }

    private void read() {
        //.... Reades the file and initializes the class attributes
    }

    private void readFirstLine(String[] inputLine) {
        //.... Method used by the read() method
    }

    private void readSecondLine(String[] inputLine) {
        //.... Method used by the read() method
    }

    private void readCustomerLine(String[] inputLine) { 
        //.... Method used by the read() method
    }

    private void constructGroupOfCustomers() {
        //this.groupOfCustomers = new GroupOfCustomers(**attributes of the class**);
    }

    public GroupOfCustomers getConstructedGroupOfCustomers() {
        return this.GroupOfCustomers;
    }
}

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

GroupOfCustomersImporter importer = new GroupOfCustomersImporter(filepath)
importer.createCSVReader();
read();
GroupOfCustomer group = constructGoupOfCustomerInstance();

আমি এটি পছন্দ করি কারণ আমি ক্লায়েন্টের পাশের কোডে কোডের অকেজো লাইনগুলি প্রয়োগের বিশদ দিয়ে ক্লায়েন্ট শ্রেণিকে বিরক্ত করতে চাই না।

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

উত্তর:


17

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

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

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

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

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


1

আপনার শ্রেণি নির্মাতাকে প্রচুর পদ্ধতি কল করার বিকল্প হিসাবে - যা আমি সম্মত হ'ল সাধারনত এড়ানো একটি অভ্যাস - আপনি ক্লায়েন্টকে বিরক্ত করতে চান না এমন অতিরিক্ত সমস্ত প্রারম্ভিক উপাদানগুলি পরিচালনা করার জন্য আপনি একটি ফ্যাক্টরি পদ্ধতি তৈরি করতে পারেন could সঙ্গে পার্শ্ব. এর অর্থ হ'ল আপনি আপনার constructGroupOfCustomers()পদ্ধতির মতো কিছু দেখতে পাবলিক হিসাবে দেখানোর জন্য কোনও পদ্ধতি উন্মোচিত করবেন এবং এটি আপনার শ্রেণীর স্থির পদ্ধতি হিসাবে ব্যবহার করছেন:

GroupOfCustomersImporter importer = 
    new GroupOfCustomersImporter.CreateInstance();

বা পৃথক কারখানার শ্রেণির পদ্ধতি হিসাবে সম্ভবত:

ImporterFactory factory = new ImporterFactory();
GroupOfCustomersImporter importer = factory.CreateGroupOfCustomersImporter();

এগুলি হ'ল প্রথম দিকের প্রথম দম্পতি যা সরাসরি আমার মাথার উপরে উঠে যায়।

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


1

আমার নিজের উত্তর যুক্ত করা হচ্ছে, যেহেতু এটি কোনও মন্তব্যের জন্য দীর্ঘ সময় শেষ হয়েছে।

আপনি একদম ঠিক বলেছেন যে এনক্যাপসুলেশন এবং পরীক্ষাটি সম্পূর্ণ বিপরীত - আপনি যদি প্রায় সমস্ত কিছু গোপন করেন তবে এটি পরীক্ষা করা শক্ত।

যাইহোক, আপনি ফাইলের পরিবর্তে একটি স্ট্রিম দিয়ে উদাহরণটিকে আরও পরীক্ষামূলক করে তুলতে পারেন - এইভাবে আপনি কেবল মেমরি থেকে একটি পরিচিত সিএসভি সরবরাহ করতে চান, বা যদি আপনি চান তবে একটি ফাইল সরবরাহ করেন। যখন আপনাকে HTTP সমর্থন যুক্ত করতে হবে তখন এটি আপনার শ্রেণিকে আরও শক্তিশালী করে তুলবে;)

এছাড়াও, অলস-আরআইডি ব্যবহার করে দেখুন:

public class Csv
{
  private CustomerList list;

  public CustomerList get()
  {
    if(list == null)
        load();
     return list;
  }
}

1

কনস্ট্রাক্টরের কিছু ভেরিয়েবল বা অবজেক্টের অবস্থা আরম্ভ করা ছাড়া খুব বেশি কিছু করা উচিত নয়। কনস্ট্রাক্টরে খুব বেশি কাজ করা রানটাইম ব্যতিক্রম বাড়াতে পারে। আমি ক্লায়েন্টকে এরকম কিছু করা এড়াতে চেষ্টা করব:

MyClass a;
try {
   a = new MyClass();
} catch (MyException e) {
   //do something
}

পরিবর্তে:

MyClass a = new MyClass(); // Or a factory method
try {
   a.doSomething();
} catch (MyException e) {
   //do something
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.