একটি 'চেষ্টা ... ধরা ... অবশেষে' নির্মাণের 'অবশেষে' অংশটি কি এখনও প্রয়োজনীয়?


25

কিছু ভাষা (যেমন সি ++ এবং পিএইচপি এর প্রাথমিক সংস্করণ) finallyকোনও try ... catch ... finallyনির্মাণের অংশটিকে সমর্থন করে না । কি finallyকি কখনো প্রয়োজনীয়? কারণ এতে থাকা কোডটি সর্বদা চলতে থাকে, কেন আমি এই কোডটি try ... catchকোনও finallyধারা ছাড়াই একটি ব্লকের পরে রাখি না ? কেন একটি ব্যবহার? (আমি ব্যবহার / ব্যবহার না করার জন্য কোনও কারণ / অনুপ্রেরণা খুঁজছি finally, 'ধরা' কেটে যাওয়ার কোনও কারণ নয় বা কেন এটি করা আইনত।)


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
maple_shaft

উত্তর:


36

অন্যেরা যা বলেছে তা ছাড়াও, ক্যাচ ক্লজের ভিতরে কোনও ব্যতিক্রম ছুঁড়ে ফেলাও সম্ভব। এই বিবেচনা:

try { 
    throw new SomeException();
} catch {
    DoSomethingWhichUnexpectedlyThrows();
}
Cleanup();

এই উদাহরণস্বরূপ, Cleanup()ফাংশনটি কখনই চলবে না, কারণ একটি ব্যতিক্রম ক্যাচ ক্লজটিতে ফেলে দেয় এবং কল স্ট্যাকের পরবর্তী সর্বোচ্চ আপটি এটি ধরবে। শেষ অবধি ব্যবহার করা এই ঝুঁকিটিকে সরিয়ে দেয় এবং বুট করার জন্য কোড ক্লিনার করে তোলে।


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

56

অন্যরা যেমন উল্লেখ করেছে, tryআপনি যতটা সম্ভব ব্যতিক্রম না ধরলে কোনও বিবৃতি দেওয়ার পরে কোডের কোনও গ্যারান্টি নেই । এই বলেছিল:

try {
   mightThrowSpecificException();
} catch (SpecificException e) {
   handleError();
} finally {
   cleanUp();
}

1 টি পুনরায় লেখা যেতে পারে :

try {
   mightThrowSpecificException();
} catch (SpecificException e) {
   try {
       handleError();
   } catch (Throwable e2) {
       cleanUp();
       throw e2;
   }
} catch (Throwable e) {
   cleanUp();
   throw e;
}
cleanUp();

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

সি ++ এর finallyকারণ নেই কারণ বর্জন স্ট্রস্ট্রুপ বিশ্বাস করে যে RAII ভাল , বা বেশিরভাগ ক্ষেত্রে কমপক্ষে যথেষ্ট রয়েছে:

সি ++ কেন "অবশেষে" নির্মাণ সরবরাহ করে না?

কারণ সি ++ এমন বিকল্পকে সমর্থন করে যা প্রায় সর্বদা ভাল: "রিসোর্স অধিগ্রহণ ইনিশিয়ালাইজেশন" কৌশল (টিসি ++ পিএল 3 বিভাগ 14.4)। স্থানীয় ধারণাটি কোনও স্থানীয় অবজেক্টের মাধ্যমে কোনও উত্সকে উপস্থাপন করা হয়, যাতে স্থানীয় অবজেক্টের ডেস্ট্রাক্টর রিসোর্সটি প্রকাশ করে। এইভাবে, প্রোগ্রামারটি রিসোর্সটি প্রকাশ করতে ভুলতে পারে না।


1 স্ট্যাক ট্রেস তথ্য না হারিয়ে সমস্ত ব্যতিক্রম এবং পুনর্বিবেচনার জন্য নির্দিষ্ট কোডটি ভাষা অনুসারে পরিবর্তিত হয়। আমি জাভা ব্যবহার করেছি, যেখানে ব্যতিক্রম তৈরি হওয়ার পরে স্ট্যাক ট্রেস ধরা পড়ে। সি # তে আপনি কেবল ব্যবহার করবেন throw;


8
handleError()দ্বিতীয় ক্ষেত্রেও আপনাকে ব্যতিক্রম ধরতে হবে , না?
জুড়ি রবল

1
আপনি একটি ত্রুটি নিক্ষেপ করা হতে পারে। আমি catch (Throwable t) {}এটিকে পুনরায় বলব, পুরো প্রাথমিক ব্লকের চারপাশে ব্লক ধরুন ( handleErrorপাশাপাশি
থ্রোয়েবলদের ধরতেও

1
কল করার সময় আপনি বাদ দেওয়া অতিরিক্ত ট্রেক-ক্যাচ আসলে আমি যুক্ত করব handleErro();যা শেষ পর্যন্ত ব্লকগুলি কেন কার্যকর (যদিও এটি আসল প্রশ্ন ছিল না) কেন এটি আরও ভাল যুক্তিযুক্ত করে তুলবে।
অ্যালেক্স

1
এই উত্তরটি কেন সি ++ এর সাথে নেই, এই প্রশ্নটি আসলেই সমাধান করে না finally, যা অনেক বেশি প্রয়োজনীয়।
ডেড এমজি

1
@ অ্যাজিহ্যামার্থিফ নির্দিষ্ট ব্যতিক্রমের জন্য নেস্টেড tryভিতরে রয়েছে । দ্বিতীয়ত, এটি সম্ভবত আপনি জানেন না যে আপনি ব্যতিক্রমটি পরীক্ষা না করা পর্যন্ত আপনি ত্রুটিটি সফলভাবে পরিচালনা করতে পারবেন কিনা বা ব্যতিক্রমের কারণ আপনাকে ত্রুটি পরিচালনা করতে বাধা দেয় (কমপক্ষে সেই স্তরে)। আই / ও করার সময় এটি মোটামুটি সাধারণ। পুনঃসূত্রটি এখানে রয়েছে কারণ রানগুলির গ্যারান্টি দেওয়ার একমাত্র উপায় হ'ল সমস্ত কিছু ধরা , তবে মূল কোডটি ব্লকের উদ্ভূত ব্যতিক্রমগুলি উপরের দিকে প্রচার করতে দেয় । catchcleanUpcatch (SpecificException e)
ডোভাল

22

finally ব্লকগুলি সাধারণত সংস্থানগুলি সাফ করতে ব্যবহৃত হয় যা একাধিক রিটার্ন স্টেটমেন্টগুলি ব্যবহার করার সময় পাঠযোগ্যতার সাথে সহায়তা করতে পারে:

int DoSomething() {
    try {
        open_connection();
        return get_result();
    }
    catch {
        return 2;
    }
    finally {
        close_connection();
    }
}

বনাম

int DoSomething() {
    int result;
    try {
        open_connection();
        result = get_result();
    }
    catch {
        result = 2;
    }
    close_connection();
    return result;
}

2
আমি মনে করি এটিই সেরা উত্তর। জেনেরিক ব্যতিক্রমের জন্য প্রতিস্থাপন হিসাবে শেষ পর্যন্ত ব্যবহার করা কেবল বিরক্তিজনক বলে মনে হচ্ছে। সঠিক ব্যবহারের কেস হল রিসোর্সেস বা অ্যানালগাসিক ক্রিয়াকলাপ to
কিক

3
সম্ভবত আরও সাধারণ চেষ্টা ব্লকের ভিতরে না গিয়ে চেষ্টা ব্লকের ভিতরে ফিরে আসছে।
মাইকেল অ্যান্ডারসন

আমার মনে, কোডটি ব্যবহারের পর্যাপ্তরূপে ব্যাখ্যা করে না finally। (আমি যেখানে কাজ করি সেখানে একাধিক রিটার্ন স্টেটমেন্ট নিরুত্সাহিত
হওয়ায়

15

আপনি স্পষ্টতই ইতিমধ্যে উদ্দীপিত হয়ে গেছেন, হ্যাঁ, সি ++ সেই প্রক্রিয়া ছাড়াই একই ক্ষমতা সরবরাহ করে। যেমন, কঠোরভাবে বলতে গেলে, try/ finallyপ্রক্রিয়াটি আসলেই প্রয়োজনীয় নয়।

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

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

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

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

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

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

class Foo {
    // ...
public:
    void do_whatever() { if (xyz) throw something; }
    ~Foo() { /* handle cleanup */ }
};

... এবং ক্লায়েন্ট কোডটি দেখতে এরকম কিছু দেখাচ্ছে:

void f() { 
    Foo f;
    f.do_whatever();
    // possibly more code that might throw here
}

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

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

যদিও আমি এটিকে উপরে "জাভা পদ্ধতির" বলেছি, try/ finallyএবং অন্যান্য নামের অনুরূপ প্রক্রিয়া পুরোপুরি জাভাতেই সীমাবদ্ধ নয়। একটি বিশিষ্ট উদাহরণের জন্য, .NET ভাষাগুলির বেশিরভাগ (সমস্ত?) (যেমন, সি #) একই সরবরাহ করে।

জাভা এবং সি # উভয়ের সাম্প্রতিক পুনরাবৃত্তিগুলি এই ক্ষেত্রে "ক্লাসিক" জাভা এবং সি ++ এর মধ্যে অর্ধপথের কিছু দেয়। সি # তে, এমন কোনও বস্তু যা তার ক্লিনআপটি স্বয়ংক্রিয় করতে চায় IDisposableইন্টারফেসটি প্রয়োগ করতে পারে , যা একটি Disposeপদ্ধতি প্রদান করে যা (অন্তত অস্পষ্টভাবে) সি ++ ডিস্ট্রাক্টরের অনুরূপ। এই যখন করতে একটি মাধ্যমে ব্যবহার করা যেতে try/ finallyজাভা মত, সি # টাস্কের একটি স্বয়ংক্রিয়রূপে সামান্য একটি সঙ্গে আরো usingএ বক্তব্যে আপনি কি সম্পদ হিসাবে একটি সুযোগ প্রবেশ করানো হয় তৈরি করা হবে, এবং ধ্বংস যখন সুযোগ থেকে প্রস্থান করা হয় সংজ্ঞায়িত করতে দেয়। সি ++ দ্বারা সরবরাহিত অটোমেশন এবং নিশ্চিতকরণের স্তরের তুলনায় এখনও কম, তবে এটি এখনও জাভার তুলনায় যথেষ্ট উন্নতি। বিশেষত, ক্লাস ডিজাইনার কীভাবে তার বিশদটি কেন্দ্রিয় করতে পারেনএর বাস্তবায়নে শ্রেণিকে নিষ্পত্তি করা IDisposable। ক্লায়েন্ট প্রোগ্রামারের জন্য যা অবশিষ্ট রয়েছে তা হ'ল একটি usingবিবৃতি লেখার কম বোঝা হ'ল IDisposableইন্টারফেসটি কখন হওয়া উচিত তা নিশ্চিত করা যায়। জাভা 7 এবং আরও নতুনতে, দোষীদের সুরক্ষার জন্য নামগুলি পরিবর্তন করা হয়েছে, তবে মূল ধারণাটি মূলত অভিন্ন।


1
নিখুঁত উত্তর. Destructors হয় সি ++ মধ্যে আছে-আবশ্যক বৈশিষ্ট্য।
টমাস এডিং

13

বিশ্বাস হচ্ছে না অন্য কেউ এই তুলেছে (কোন শ্লেষ উদ্দেশ্যে) - আপনি না প্রয়োজন একটি ধরা দফা!

এটি পুরোপুরি যুক্তিযুক্ত:

try 
{
   AcquireManyResources(); 
   DoSomethingThatMightFail(); 
}
finally 
{
   CleanUpThoseResources(); 
}

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

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


9

আপনি যদি প্রত্যাশা করছিলেন না এবং যদি ব্যতিক্রম ছুঁড়ে ফেলা হয় তবে কী হবে। চেষ্টাটি এর মাঝামাঝি সময়ে প্রস্থান করবে এবং কোনও ক্যাচ ক্লজ কার্যকর করা হবে না।

পরিশেষে অবরুদ্ধটি হ'ল এটির সাথে সহায়তা করা এবং নিশ্চিত হওয়া যে কোনও ব্যতিক্রম পরিষ্কার-পরিচ্ছন্নতা ঘটবে।


4
এটি কোনওর জন্য পর্যাপ্ত কারণ নয় finally, কারণ আপনি "অপ্রত্যাশিত" ব্যতিক্রমগুলি catch(Object)বা catch(...)ক্যাচ-অলসগুলি প্রতিরোধ করতে পারেন ।
এমএসএলটাররা

1
যা চারপাশের কাজের মতো শোনাচ্ছে। ধারণাগত অবশেষে পরিষ্কার। যদিও আমি এটি খুব কমই ব্যবহার করার জন্য স্বীকার করতে হবে।
দ্রুত_

7

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

ডেস্ট্রাক্টরবিহীন ভাষায় (যেমন জাভা) finallyদফা ব্যতীত সঠিক পরিচ্ছন্নতা অর্জন করা কঠিন (সম্ভবত অসম্ভবও) is এনবি - জাভাতে একটি finaliseপদ্ধতি রয়েছে তবে এটি কখনও কল করার কোনও গ্যারান্টি নেই।


এটা খেয়াল করা জরুরী সম্পদ পরিষ্কারের যখন ধ্বংস হয় যে destructors সাহায্যের দরকারী হতে পারে নির্ণায়ক । যদি আমরা না জানি কখন অবজেক্টটি ধ্বংস হবে এবং / বা আবর্জনা সংগ্রহ করা হবে, তবে ধ্বংসকারীরা যথেষ্ট নিরাপদ নয়।
মরউভেন

@ মরওভেন - ভালো কথা। আমি জাভা সম্পর্কিত আমার রেফারেন্সের সাথে এটি ইঙ্গিত দিয়েছিলাম finaliseতবে আমি এই মুহুর্তে ধ্বংসকারী / চূড়ান্ত সম্পর্কে রাজনৈতিক যুক্তিতে notোকা পছন্দ করব না।
ওল্ডরুকমুডিজিয়ন

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

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

1

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

এবং শেষ পর্যন্ত চেষ্টা করুন কোড চালানোর জন্য ডিজাইন করা হয়েছে এমনকি প্রোগ্রামিং প্রবাহ ঝাঁপিয়ে পড়ে। তা ব্যতিক্রম বা অন্য কোনও কারণে হোক। এটি কোনও উত্স অর্জন এবং ঝাঁপ দেওয়ার বিষয়ে চিন্তা না করেই এটি পরিষ্কার হয়ে গেছে তা নিশ্চিত করার একটি পরিষ্কার উপায়।


3
.NET এ তারা পৃথক প্রক্রিয়া ব্যবহার করে প্রয়োগ করা হয়; জাভাতে, তবে, জেভিএম দ্বারা স্বীকৃত একমাত্র নির্মাণটি শব্দার্থগতভাবে "অন ত্রুটি গেটো" সমতুল্য, এটি একটি প্যাটার্ন যা সরাসরি সমর্থন করে try catchতবে তা নয় try finally; পরবর্তীটির কোড ব্যবহার করে কোডটি কেবলমাত্র প্রাক্তন ব্যবহার করে কোডে রূপান্তরিত হয়, কোডের finallyসমস্ত দাগে ব্লকের সামগ্রীতে অনুলিপি করে যেখানে এটি কার্যকর করতে পারে।
সুপারক্যাট

@ সুপের্যাট চমৎকার, জাভা সম্পর্কে অতিরিক্ত তথ্যের জন্য ধন্যবাদ।
পিটার বি

1

যেহেতু এই প্রশ্নটি সি ++ কে ভাষা হিসাবে নির্দিষ্ট করে না আমি সি ++ এবং জাভা এর মিশ্রণটি বিবেচনা করব, যেহেতু তারা বস্তু ধ্বংসের জন্য পৃথক পদ্ধতি গ্রহণ করে, যা বিকল্পগুলির একটি হিসাবে প্রস্তাবিত হচ্ছে।

যে কারণে আপনি চেষ্টা-ব্লকের পরে কোডের পরিবর্তে শেষ অবধি ব্যবহার করতে পারেন

  • আপনি চেষ্টা ব্লক থেকে তাড়াতাড়ি ফিরে: এটি বিবেচনা করুন

    Database db = null;
    try {
     db = open_database();
     if(db.isSomething()) {
       return 7;
     }
     return db.someThingElse();
    } finally {
      if(db!=null)
        db.close();
    }
    

    সাথে তুলনা করা:

    Database db = null;
    int returnValue = 0;
    try {
     db = open_database();
     if(db.isSomething()) {
       returnValue = 7;
     } else {
       returnValue = db.someThingElse();
     }
    } catch(Exception e) {
      if(db!=null)
        db.close();
    }
    return returnValue;
    
  • আপনি ক্যাচ ব্লক (গুলি) থেকে তাড়াতাড়ি ফিরে আসুন: তুলনা করুন

    Database db = null;
    try {
     db = open_database();
     db.doSomething();
    } catch (DBIntegrityException e ) {
      return 7;
    } catch (DBIsADonkeyException e ) {
      return 11;
    } finally {
      if(db!=null)
        db.close();
    }
    

    বনাম:

    Database db = null;
    try {
     db = open_database();
     db.doSomething();
    } catch (DBIntegrityException e ) {
      if(db!=null) 
        db.close();
      return 7;
    } catch (DBIsADonkeyException e ) {
      if(db!=null)
        db.close();
      return 11;
    }           
    db.close();
    
  • আপনি ব্যতিক্রম পুনর্বিবেচনা। তুলনা করা:

    Database db = null;
    try {
     db = open_database();
     db.doSomething();
    } catch (DBIntegrityException e ) {
      throw convertToRuntimeException(e,"DB was wonkey");
    } finally {
      if(db!=null)
        db.close();
    }
    

    বনাম:

    Database db = null;
    try {
     db = open_database();
     db.doSomething();
    } catch (DBIntegrityException e ) {
      if(db!=null)
        db.close();
      throw convertToRuntimeException(e,"DB was wonkey");
    } 
    if(db!=null)
      db.close();
    

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

এখন সি ++ এ স্কোপ ভিত্তিক অবজেক্টগুলির সাথে পরিচালনা করা যায়। তবে আইএমও এই পদ্ধতির দুটি অসুবিধা রয়েছে 1. সিনট্যাক্স কম বন্ধুত্বপূর্ণ। ২. নির্মাণের ক্রমটি ধ্বংসের বিপরীত হওয়ায় বিষয়গুলিকে কম স্পষ্ট করা যায়।

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


1

প্রোগ্রামিং ভাষার "যৌক্তিক" সমস্ত কিছু হ'ল নির্দেশাবলী:

assignment a = b
subtract a from b
goto label
test a = 0
if true goto label

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

যেমন একটি ন্যূনতম নির্দেশিকা সেট ব্যবহার করে প্রকৃত হার্ডওয়্যারের জন্য পুরানো বিশ্বমানের কম্পিউটারটি দেখুন ।


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

1
মুল বক্তব্যটি হ'ল যে কোনও ভাষা বাস্তবায়ন করে কেবল এই 5 টি অপারেশন যে কোনও অ্যালগোরিদম বাস্তবায়িত করতে পারে - তাত্পর্যপূর্ণ হলেও। উচ্চ স্তরের ভাষাগুলির বেশিরভাগ ভার্সেট / অপারেটরগুলি "প্রয়োজনীয়" নয় যদি লক্ষ্যটি কেবল একটি অ্যালগরিদম বাস্তবায়ন করা হয়। যদি লক্ষ্যটি পাঠ্যযোগ্য রক্ষণাবেক্ষণযোগ্য কোডের দ্রুত বিকাশ হয় তবে সর্বাধিক প্রয়োজনীয় তবে "পাঠযোগ্য" এবং "রক্ষণাবেক্ষণযোগ্য" পরিমাপযোগ্য এবং চূড়ান্ত বিষয়গত নয়। সুন্দর ভাষা বিকাশকারীরা প্রচুর বৈশিষ্ট্য রেখেছেন: যদি তাদের কয়েকটি ব্যবহার না করে তবে সেগুলি ব্যবহার করবেন না।
জেমস অ্যান্ডারসন

0

আসলে আমার কাছে বৃহত্তর ব্যবধানটি সাধারণত সেই ভাষাগুলিতে হয় যেগুলি সমর্থন করে finallyতবে ধ্বংসকারীদের অভাব হয়, কারণ আপনি নিজেই ক্লিনআপ নিয়ে কাজ না করে কেন্দ্রীয় স্তরে ধ্বংসকারীদের মাধ্যমে "ক্লিনআপ" (যা আমি দুটি বিভাগে পৃথক করব) এর সাথে যুক্ত সমস্ত যুক্তি মডেল করতে পারেন you প্রতিটি প্রাসঙ্গিক ফাংশনে যুক্তি। আমি যখন সি # বা জাভা কোডটি ম্যানুয়ালি মুটেক্সগুলি আনলক করা এবং finallyব্লকগুলিতে ফাইলগুলি বন্ধ করার মতো কাজগুলি করতে দেখি তখন সেই পুরানো এবং সি কোডের মতো মায়া অনুভব করে যখন সমস্ত কিছুই সি ++ এ ধ্বংসকারীদের মাধ্যমে স্বয়ংক্রিয়ভাবে সেই দায়িত্ব থেকে মানুষকে মুক্তি দেয়।

তবে, সি ++ অন্তর্ভুক্ত করা থাকলে আমি এখনও একটি হালকা সুবিধা পাব finallyএবং এটি কারণ দুই ধরণের ক্লিন আপগুলি রয়েছে:

  1. স্থানীয় সম্পদগুলি ধ্বংস / মুক্ত / আনলকিং / ক্লোজিং / ইত্যাদি (ধ্বংসকারীরা এটির জন্য উপযুক্ত)।
  2. বাহ্যিক পার্শ্ব প্রতিক্রিয়াগুলি পূর্বাবস্থায় ফেরা / ঘুরিয়ে দেওয়া (ধ্বংসকারীরা এটির জন্য পর্যাপ্ত)।

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

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

try
{
    // Cause external side effects. These side effects should
    // be undone if we don't finish successfully.
}
rollback
{
    // Reverse external side effects. This block is *only* executed 
    // if the 'try' block above faced a premature return out 
    // of the function. It is different from 'finally' which 
    // gets executed regardless of whether or not the function 
    // exited prematurely. This block *only* gets executed if we 
    // exited prematurely from  the try block so that we can undo 
    // whatever side effects it failed to finish making. If the try 
    // block succeeded and didn't face a premature exit, then we 
    // don't want this block to execute.
}

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

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


-9

সি ++ ভাষা সম্পর্কে অন্যান্য অনেকগুলি অস্বাভাবিক জিনিসের মতো, কোনও try/finallyনির্মাণের অভাব হ'ল একটি ডিজাইনের ত্রুটি, যদি আপনি এমনকি এটি এমন কোনও ভাষায় বলতে পারেন যা প্রায়শই প্রদর্শিত হয় যা কোনও আসল নকশা কাজই করেনি।

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

দ্বিতীয়ত, যা finallyকরতে পারে তা হ'ল অবজেক্টের ধ্বংস। সি ++ এ আরআইআই দিয়ে যা করা হয় তার বেশিরভাগটি ডেল্ফি ভাষায় বর্ণিত হবে, যার আবর্জনা সংগ্রহ নেই, নিম্নলিখিত প্যাটার্ন সহ:

myObject := MyClass.Create(arguments);
try
   doSomething(myObject);
finally
   myObject.Free();
end;

এটি স্পষ্ট করে দেওয়া RAII প্যাটার্নটি; যদি আপনি কোনও সি ++ রুটিন তৈরি করতে থাকেন যা উপরের প্রথম এবং তৃতীয় লাইনের সমতুল্য থাকে তবে সংকলকটি কী উত্পন্ন করবে তা আমি তার বুনিয়াদি কাঠামোর মতো লিখেছি like এবং এটি try/finallyসি ++ সরবরাহ করে এমন একমাত্র নির্মাণের একমাত্র অ্যাক্সেস , সি ++ বিকাশকারীরা বরং এটির একটি মায়োপিক দৃষ্টিভঙ্গি দিয়ে শেষ করে try/finally: যখন আপনার সমস্ত কিছু হাতুড়ি হয়ে যায়, তখন কথা বলতে গেলে সমস্ত কিছুই একজন ধ্বংসকারী হিসাবে দেখতে শুরু করে।

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

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

dataset.DisableControls();
try
   LoadData(dataset);
finally
   dataset.EnableControls();
end;

স্পষ্টতই, এখানে কোনও জিনিস ধ্বংস হচ্ছে না, এবং এটির প্রয়োজন নেই। কোডটি সহজ, সংক্ষিপ্ত, সুস্পষ্ট এবং দক্ষ।

এটি সি ++ এ কীভাবে হবে? ঠিক আছে, প্রথমে আপনাকে একটি সম্পূর্ণ ক্লাস কোড করতে হবে । এটা সম্ভবত হতে হবে DatasetEnablerবা somesuch জিনিস। এর পুরো অস্তিত্ব রাইআইআই সহায়ক হিসাবে থাকবে। তারপরে আপনার এই জাতীয় কিছু করা দরকার:

dataset.DisableControls();
{
   raiiGuard = DatasetEnabler(dataset);
   LoadData(dataset);
}

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

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


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