কোনও ওও প্রোগ্রামকে একটি কার্যক্ষম মধ্যে কীভাবে রিফ্যাক্টর করবেন?


26

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

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


6
আমি মনে করি না এটি সম্ভব। আপনাকে আবার নতুন করে ডিজাইন করতে হবে (এবং নতুন করে লিখতে হবে)।
ব্রায়ান চেন

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

11
@ ডকব্রাউন, ওওপি একটি পরিবর্তনীয় অবস্থার উপর খুব বেশি নির্ভর করে। স্টেটলেস অবজেক্টস বর্তমান ওওপি ডিজাইনের অনুশীলনে ভালভাবে খাপ খায় না।
এসকে-যুক্তি

9
@ এসকে-যুক্তি: কীটি হ'ল রাজ্যহীন বস্তু নয়, তবে অপরিবর্তনীয় বস্তু। এমনকি যখন অবজেক্টগুলি পরিবর্তনীয় হয় ততক্ষণ তারা প্রদত্ত প্রসঙ্গে পরিবর্তিত না হওয়া অবধি সিস্টেমের কার্যকরী অংশে ব্যবহার করতে পারে। তদুপরি, আমি অনুমান করি আপনি জানেন যে অবজেক্ট এবং ক্লোজারগুলি বিনিময়যোগ্য। সুতরাং এটি সমস্ত দেখায় যে ওওপি এবং "ক্রিয়ামূলক" বিপরীত নয়।
ডক ব্রাউন

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

উত্তর:


31

ফাংশনাল প্রোগ্রামিং সংজ্ঞা

দ্য জয় অফ ক্লোজারের সাথে পরিচয় করিয়ে দিয়েছিলেন :

ফাংশনাল প্রোগ্রামিং এমন একটি কম্পিউটিং শর্ত যা একটি নিরাকার সংজ্ঞা আছে। আপনি যদি 100 প্রোগ্রামারকে তাদের সংজ্ঞার জন্য জিজ্ঞাসা করেন তবে আপনি সম্ভবত 100 টি বিভিন্ন উত্তর পাবেন ...

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

স্কালার দ্বিতীয় সংস্করণে প্রোগ্রামিং পি। 10 এর নিম্নলিখিত সংজ্ঞা রয়েছে:

কার্যকরী প্রোগ্রামিং দুটি প্রধান ধারণা দ্বারা পরিচালিত হয়। প্রথম ধারণাটি হ'ল ফাংশনগুলি হ'ল প্রথম শ্রেণীর মান ... আপনি অন্যান্য ক্রিয়াকলাপগুলিতে যুক্তি হিসাবে ফাংশনগুলি পাস করতে পারেন, ফাংশন থেকে ফলাফল হিসাবে তাদের ফিরিয়ে দিতে পারেন বা এগুলি ভেরিয়েবলে সঞ্চয় করতে পারেন ...

ফাংশনাল প্রোগ্রামিংয়ের দ্বিতীয় প্রধান ধারণাটি হ'ল কোনও প্রোগ্রামের ক্রিয়াকলাপগুলিতে ডাটা পরিবর্তনের পরিবর্তে আউটপুট মানগুলিতে ম্যাপ করা উচিত।

যদি আমরা প্রথম সংজ্ঞা গ্রহণ করি, তবে আপনার কোডটিকে "কার্যকরী" করার জন্য আপনার কেবলমাত্র লুপগুলি ভিতরে আউট করা উচিত। দ্বিতীয় সংজ্ঞায় অপরিবর্তনীয়তা অন্তর্ভুক্ত।

প্রথম শ্রেণির কার্যাদি

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

অনুজ্ঞাসূচক:

for (Passenger p : Bus.getPassengers()) {
    p.debit(fare);
}

কার্যকরী (স্কালায় একটি বেনাম ফাংশন বা "ল্যাম্বদা" ব্যবহার করে):

myBus = myBus.forEachPassenger(p:Passenger -> { p.debit(fare) })

আরও চিনিযুক্ত স্কেল সংস্করণ:

myBus = myBus.forEachPassenger(_.debit(fare))

প্রথম-শ্রেণীর ক্রিয়াকলাপ

যদি আপনার ভাষা প্রথম শ্রেণির ফাংশনগুলি সমর্থন করে না, তবে এটি খুব কুশ্রী হতে পারে। জাভা 7 বা তার আগে, আপনাকে "ফাংশনাল অবজেক্ট" ইন্টারফেসটি এইভাবে সরবরাহ করতে হবে:

// Java 8 has java.util.function.Consumer, but in earlier
// versions you have to roll your own:
public interface Consumer<T> {
    public void accept(T t);
}

তারপরে বাস শ্রেণি একটি অভ্যন্তরীণ পুনরুক্তি সরবরাহ করে:

public void forEachPassenger(Consumer<Passenger> c) {
    for (Passenger p : passengers) {
        c.accept(p);
    }
}

অবশেষে, আপনি একটি বেনাম ফাংশন অবজেক্টটি বাসে পাস করুন:

// Java 8 has syntactic sugar to make this look more like
// the Scala solution, but earlier versions require manually
// instantiating a "Function Object," in this case, a
// Consumer:
Bus.forEachPassenger(new Consumer<Passenger>() {
    @Override
    public void accept(final Passenger p) {
        p.debit(fare);
    }
}

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

public static class MutableIntWrapper {
    private int i;
    private MutableIntWrapper(int in) { i = in; }
    public static MutableIntWrapper ofZero() {
        return new MutableIntWrapper(0);
    }
    public int value() { return i; }
    public void increment() { i++; }
}

final MutableIntWrapper count = MutableIntWrapper.ofZero();
Bus.forEachPassenger(new Consumer<Passenger>() {
    @Override
    public void accept(final Passenger p) {
        p.debit(fare);
        count.increment();
    }
}

System.out.println(count.value());

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

এই কদর্যতা জাভা 8-এ স্থির করা হয়েছে, তবে প্রথম শ্রেণির ফাংশনের অভ্যন্তরে পরীক্ষিত ব্যতিক্রমগুলি পরিচালনা করা এখনও সত্যই খারাপ এবং জাভা এখনও তার সমস্ত সংগ্রহগুলিতে পরিবর্তনের অনুমান বহন করে। যা আমাদের প্রায়শই এফপির সাথে যুক্ত অন্যান্য লক্ষ্যে নিয়ে আসে:

অপরিবর্তনীয়তা

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

বিশুদ্ধতা

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

এটি ফাংশনাল প্রোগ্রামিংয়ে বলা হয়েছে যে, "কাজ শেষ করার জন্য সাধারণত কিছু অশুভের প্রয়োজন হয়।" 100% বিশুদ্ধতা সাধারণত লক্ষ্য নয়। পার্শ্ব প্রতিক্রিয়া হ্রাস করা হয়।

উপসংহার

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

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

দ্রষ্টব্য

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

public interface Function<T,R> {
    public R apply(T t);
    // Note: I'm leaving out Java 8's compose() method here for simplicity
}

তারপরে বাসে:

public Bus mapPassengers(Function<Passenger,Passenger> c) {
    // I have to use a mutable collection internally because Java
    // does not have immutable collections that return modified copies
    // of themselves the way the Clojure and Scala collections do.
    List<Passenger> newPassengers = new ArrayList(passengers.size());
    for (Passenger p : passengers) {
        newPassengers.add(c.apply(p));
    }
    return Bus.of(driver, Collections.unmodifiableList(passengers));
}

শেষ অবধি, বেনামে ফাংশন অবজেক্টগুলি জিনিসগুলির পরিবর্তিত স্থিতি (নতুন যাত্রী সহ একটি নতুন বাস) প্রদান করে। এটি ধরে নিয়েছে যে পি.ডিবিট () এখন মূলের চেয়ে কম অর্থ নিয়ে একটি নতুন অচল যাত্রী ফিরিয়ে দেয়:

Bus b = b.mapPassengers(new Function<Passenger,Passenger>() {
    @Override
    public Passenger apply(final Passenger p) {
        return p.debit(fare);
    }
}

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


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

এবং যত তাড়াতাড়ি কোনও ফাংশন কোনও মান ফিরিয়ে দেয় না, হঠাৎ ফাংশনটি অন্যদের সাথে তৈরি করা যায় না এবং আপনি কার্যকরী রচনার সমস্ত বিমূর্ততা হারাবেন। আপনি ফাংশনটি জায়গায় বস্তুটি পরিবর্তন করতে এবং তারপরে বস্তুটি ফিরিয়ে আনতে পারেন, তবে এটি যদি এই কাজটি করে তবে কেবল ফাংশনটিকে একটি পরামিতি হিসাবে গ্রহণ করতে এবং তার প্যারেন্ট অবজেক্টের সীমানা থেকে মুক্ত করতে হবে না কেন? প্যারেন্ট অবজেক্ট থেকে মুক্তি এটি অন্যান্য ধরণের ক্ষেত্রেও কাজ করতে সক্ষম হবে যা আপনি যে এফপির অনুপস্থিত তার আরও একটি গুরুত্বপূর্ণ অংশ: অ্যাবস্ট্রাকশন টাইপ করুন। আপনার পেচেনজারটি কেবল যাত্রীদের বিরুদ্ধে কাজ করে ...
জিমি হোফা

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

@ জিমিহোফা আপনি আমার উদাহরণটির সম্পর্কে অত্যন্ত ন্যায্য সমালোচনা করেছেন। জাভা 8 কনজিউমার ইন্টারফেসের মাধ্যমে আমি পরিবর্তনীয়তায় প্রবৃত্ত হয়েছিলাম। এছাড়াও, এফপির কুউসার / কুয়াশা সংজ্ঞাতে অপরিবর্তনীয়তা অন্তর্ভুক্ত করা হয়নি এবং আমি পরে ওডারস্কি / চামচ / ভেনার্স সংজ্ঞা যুক্ত করেছি। আমি আসল উদাহরণটি রেখে দিয়েছি, তবে নীচে একটি "পিএস" বিভাগের অধীনে একটি নতুন, অপরিবর্তনীয় সংস্করণ যুক্ত করেছি। এটা কুৎসিত. তবে আমি মনে করি এটি মূলগুলির অভ্যন্তরীণ পরিবর্তনগুলি বদলে নতুন বস্তু উত্পাদন করার জন্য অবজেক্টগুলিতে অভিনয় করে তা প্রদর্শন করে demonst দুর্দান্ত মন্তব্য!
গ্লেনপিটারসন

1
এই কথোপকথনটি হোয়াইটবোর্ডে অব্যাহত রয়েছে: chat.stackexchange.com/transcript/message/11702383#11702383
গ্লেনপিটারসন

12

এটি আমার "অভিজ্ঞতা অর্জন" করার অভিজ্ঞতা আছে। শেষ পর্যন্ত, আমি এমন কিছু নিয়ে আসিনি যা পুরোপুরি কার্যকর হয়, তবে আমি এমন কিছু নিয়ে এসেছি যার সাথে আমি খুশি। আমি এটি কীভাবে করেছি তা এখানে:

  • সমস্ত বাহ্যিক অবস্থাকে ফাংশনের একটি প্যারামিটারে রূপান্তর করুন। EG: যদি কোনও বস্তুর পদ্ধতি পরিবর্তিত হয় xতবে এটি তৈরি করুন যাতে xকল করার পরিবর্তে পদ্ধতিটি পাস হয় this.x
  • বস্তু থেকে আচরণ সরান।
    1. অবজেক্টের ডেটা সর্বজনীনভাবে অ্যাক্সেসযোগ্য করুন
    2. সমস্ত পদ্ধতিগুলিকে ফাংশনে রূপান্তর করুন যা বস্তু কল করে।
    3. ক্লায়েন্ট কোড রয়েছে যা আইটেমটিকে কল করে নতুন ফাংশনটিকে অবজেক্টের ডেটা পাস করে। উদাহরণ: রূপান্তর x.methodThatModifiesTheFooVar()মধ্যেfooFn(x.foo)
    4. বস্তু থেকে মূল পদ্ধতিটি সরান
  • উচ্চতর ক্রম ফাংশন পছন্দ মত আপনি যা করতে পারেন অনেক পুনরাবৃত্ত loops হিসেবে প্রতিস্থাপিত map, reduce, filter, ইত্যাদি

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

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

সম্পাদন করা

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

তবে আপনি যদি জাভা ব্যবহার করছেন তবে আপনি আপনার ক্লাসগুলি অনিবার্য করতে এই কৌশলগুলি ব্যবহার করতে পারেন


+1 ঠিক আপনি যা করার চেষ্টা করছেন তার উপর নির্ভর করে এটি সম্ভবত "রিফ্যাক্টরিং" ছাড়াই ডিজাইনের পরিবর্তনগুলি না করে আপনি যেতে পারেন যা ওয়াহা যায়।
এভিকাটোস

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

আমি মনে করি পরিবর্তনীয় অবস্থা থেকে মুক্তি পাওয়ার যোগ্যতা অর্জন করবে। আমি মনে করি না যে এটি ভাষায় কেবল আরও ভাল সমর্থনের প্রশ্ন, আমি মনে করি পরিবর্তন থেকে স্থাবর হতে যাওয়া মূলত সবসময় মৌলিক আর্কিটেকচারাল পরিবর্তনের প্রয়োজন যা মূলত একটি পুনর্লিখনের গঠন করে। যদিও আপনার রিফ্যাক্টরিংয়ের সংজ্ঞা উপর নির্ভর করে Ymmv।
এভিক্যাটস

@ অ্যাভিটাকোস আমার সম্পাদনা দেখুন
ড্যানিয়েল

1
@ টিউটিটি হ্যাঁ, জেএস এতটা পরিবর্তনশীল হওয়ার জন্য দুঃখজনক, তবে কমপক্ষে ক্লোজার
GlenPeterson

3

আমি মনে করি না যে প্রোগ্রামটি সম্পূর্ণরূপে রিফ্যাক্টর করা সম্ভব - আপনাকে সঠিক দৃষ্টান্তে পুনরায় নকশা ও পুনর্নির্মাণ করতে হবে।

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

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


আমি যুক্ত করব যে উল্লেখযোগ্য স্বচ্ছতার জন্য প্রচেষ্টা করা একটি ভাল প্রথম চিহ্ন mark একবার আপনার কাছে এলে আপনি কার্যকরী প্রোগ্রামিংয়ের of 50% সুবিধা পাবেন।
ড্যানিয়েল গ্রেটজার

3

আমি মনে করি নিবন্ধের এই সিরিজটি আপনি যা চান ঠিক তেমন:

খাঁটি ফাংশনাল রেট্রোগেমস

http://prog21. دادgum.com/23.html পর্ব 1

http://prog21. دادgum.com/24.html পার্ট 2

http://prog21. دادgum.com/25.html পার্ট 3

http://prog21. دادgum.com/26.html পার্ট 4

http://prog21. دادgum.com/37.html অনুসরণ করুন

সংক্ষিপ্তসারটি হ'ল:

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

অবশ্যই একটি রিয়েল-ওয়ার্ল্ড প্রোগ্রাম লেখার সময় আপনি বেশ কয়েকটি প্রোগ্রামিং শৈলীর মিশ্রণ এবং মিল পাবেন, যেখানে এটি সবচেয়ে বেশি সহায়তা করে one তবে এটি কেবলমাত্র বৈশ্বিক চলক :-) ব্যবহার করে সর্বাধিক কার্যকরী / অপরিবর্তনীয় উপায়ে একটি প্রোগ্রাম লেখার চেষ্টা এবং এটি সবচেয়ে স্প্যাগেটি উপায়ে লেখার চেষ্টা করার জন্য একটি ভাল শিক্ষার অভিজ্ঞতা: দয়া করে এটি পরীক্ষায় নয়, উত্পাদন নয়


2

OOP এবং FP- এর সাংগঠনিক কোডের দুটি বিপরীত পন্থা রয়েছে বলে আপনাকে সম্ভবত আপনার সমস্ত কোডটি ভিতরে .োকাতে হবে।

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

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

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

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