উদ্দেশ্য-সি / কোকোয় ব্যতিক্রম ছড়িয়ে দেওয়ার সর্বোত্তম উপায় কী?
উদ্দেশ্য-সি / কোকোয় ব্যতিক্রম ছড়িয়ে দেওয়ার সর্বোত্তম উপায় কী?
উত্তর:
আমি [NSException raise:format:]
নিম্নলিখিত হিসাবে ব্যবহার :
[NSException raise:@"Invalid foo value" format:@"foo of %d is invalid", foo];
এখানে সতর্কতার একটি শব্দ। উদ্দেশ্য-সি-তে, অনেকগুলি অনুরূপ ভাষার মতো নয়, সাধারণ ক্রিয়াকলাপের ক্ষেত্রে সাধারণ অপারেশনের ক্ষেত্রে ব্যতিক্রমগুলি ব্যবহার করা এড়াতে আপনার সাধারণত চেষ্টা করা উচিত।
ওবজে-সি ২.০ এর জন্য অ্যাপলের ডকুমেন্টেশনটি নিম্নলিখিতটি জানিয়েছে: "গুরুত্বপূর্ণ: ব্যতিক্রমগুলি উদ্দেশ্য-সিতে সংস্থান-নিবিড়।
অ্যাপলের ধারণাগত ব্যতিক্রমী হ্যান্ডলিং ডকুমেন্টেশন একই ব্যাখ্যা করে, তবে আরও শব্দের সাথে: "গুরুত্বপূর্ণ: আপনার প্রোগ্রামিং বা অপ্রত্যাশিত রানটাইম ত্রুটি যেমন সীমানা সংগ্রহের অ্যাক্সেস, অপরিবর্তনীয় অবজেক্টগুলিকে পরিবর্তন করার চেষ্টা, একটি অবৈধ বার্তা প্রেরণের ব্যতিক্রমগুলি ব্যবহার সংরক্ষণ করা উচিত , এবং উইন্ডো সার্ভারের সাথে সংযোগ হারাতে হবে: রানটাইমের পরিবর্তে কোনও অ্যাপ্লিকেশন তৈরি হওয়ার সময় আপনি সাধারণত ব্যতিক্রমগুলি সহ এই ধরণের ত্রুটিগুলির যত্ন নেন [[.....] ব্যতিক্রমগুলির পরিবর্তে ত্রুটিযুক্ত বস্তু (এনএসইরর) এবং কোকো ত্রুটি-বিতরণ প্রক্রিয়া হ'ল কোকো অ্যাপ্লিকেশনগুলিতে প্রত্যাশিত ত্রুটিগুলি যোগাযোগ করার প্রস্তাবিত উপায় ""
এর কারণগুলি হ'ল আংশিক অবজেক্টিভ-সি-তে প্রোগ্রামিং আইডিয়ামগুলিতে মেনে চলা (আরও সাধারণ জটিল ক্ষেত্রে রিটার্ন মানগুলি এবং বাই-রেফারেন্স প্যারামিটারগুলি (প্রায়শই এনএসইরর ক্লাস) ব্যবহার করা), আংশিকভাবে ব্যতিক্রম ছোঁড়া এবং ধরা অনেক বেশি ব্যয়বহুল এবং অবশেষে (এবং সর্বাধিক গুরুত্বপূর্ণ বিষয়গুলি) যে অবজেক্টিভ-সি ব্যতিক্রমগুলি সি এর সেটজ্যাম্প () এবং লংজ্যাম্প () ফাংশনগুলির চারপাশে একটি পাতলা মোড়ক, মূলত আপনার যত্ন সহকারে স্মৃতি হ্যান্ডলিংকে গোলমাল করছে, এই ব্যাখ্যাটি দেখুন ।
@throw([NSException exceptionWith…])
এক্সকোড @throw
বিবৃতিগুলির মতো ফাংশন থেকে বেরিয়ে যাওয়ার পয়েন্ট হিসাবে স্বীকৃতি দেয় return
। @throw
সিনট্যাক্সটি ব্যবহার করা ভুল হওয়া থেকে বিরত থাকে " কন্ট্রোলটি অ-শূন্য ফাংশনের শেষের দিকে পৌঁছতে পারে " যে সতর্কতাগুলি থেকে আপনি পেতে পারেন [NSException raise:…]
।
এছাড়াও, @throw
ক্লাস এনএসইেক্সসেপশন নয় এমন জিনিসগুলি নিক্ষেপ করতে ব্যবহার করা যেতে পারে।
সম্পর্কিত [NSException raise:format:]
। জাভা ব্যাকগ্রাউন্ড থেকে আগতদের জন্য, আপনি স্মরণ করতে পারবেন যে জাভা ব্যতিক্রম এবং রানটাইম এক্সেপশন মধ্যে পার্থক্য করে। ব্যতিক্রম একটি চেক করা ব্যতিক্রম এবং রানটাইম এক্সেপশন চেক করা হয়নি। বিশেষত, "প্রোগ্রামার ত্রুটির কারণে রানটাইম ত্রুটি" এর জন্য জাভা "স্বাভাবিক ত্রুটি অবস্থার" জন্য চেক করা ব্যতিক্রম এবং চেক করা ব্যতিক্রমগুলি ব্যবহার করার পরামর্শ দেয়। দেখে মনে হচ্ছে যে অবজেক্টিভ সি ব্যতিক্রমগুলি একই জায়গায় ব্যবহার করা উচিত যেখানে আপনি একটি চেক না করা ব্যতিক্রম ব্যবহার করবেন এবং ত্রুটি কোড রিটার্ন মান বা এনএসইরর মানগুলি যেখানে আপনি একটি চেক করা ব্যতিক্রম ব্যবহার করবেন সেখানে অগ্রাধিকার দেওয়া হবে।
আমি সংবেদনশীল বলে মনে করি এটি আপনার নিজের ক্লাসের সাথে এনএসইএসসেপশনকে বাড়িয়ে দিয়ে @ থ্রো ব্যবহার করা আরও সুন্দর। তারপরে আপনি একই ধরণের স্বরলিপি ব্যবহার করে শেষ পর্যন্ত ধরা চেষ্টা করুন:
@try {
.....
}
@catch{
...
}
@finally{
...
}
অ্যাপল এখানে কীভাবে ব্যতিক্রম ছোঁড়াবেন এবং পরিচালনা করবেন তা এখানে ব্যাখ্যা করেছে: ব্যতিক্রম ছোঁড়া ব্যতিক্রমগুলি
ওবিজেসি ২.০, যেহেতু অবজেক্টিভ-সি ব্যতিক্রমগুলি সি এর সেটজ্যাম্প () লংজ্যাম্প () এর জন্য আর একটি মোড়ক নয়, এবং সি ++ ব্যতিক্রমের সাথে সামঞ্জস্যপূর্ণ, @ চেষ্টা "বিনা মূল্যে", তবে ব্যতিক্রম ছোঁড়া এবং ধরা আরও বেশি ব্যয়বহুল।
যাইহোক, জবাব (এনএসএসর্ট এবং এনএসসিএরসেট ম্যাক্রো পরিবার ব্যবহার করে) এনএসইসেপশনকে ছুঁড়ে ফেলেছে এবং এগুলি রিস স্টেট হিসাবে ব্যবহার করার জন্য এই বুদ্ধিমানের কাজ।
ব্যতিক্রমের পরিবর্তে ব্যর্থতা যোগাযোগ করতে এনএসইরর ব্যবহার করুন।
এনএসইরর সম্পর্কে দ্রুত পয়েন্টগুলি:
এনএসইরর সি স্টাইলের ত্রুটি কোডগুলি (পূর্ণসংখ্যা) এর মূল কারণটি পরিষ্কারভাবে সনাক্ত করতে দেয় এবং আশা করি ত্রুটি হ্যান্ডলারের ত্রুটিটি কাটিয়ে উঠতে অনুমতি দেয়। আপনি এনএসইরর এর উদাহরণগুলিতে এস লাইব্রেরি থেকে সি লাইব্রেরি থেকে ত্রুটি কোডগুলি খুব সহজেই মোড়ানো করতে পারেন।
এনএসইরর এর একটি অবজেক্ট হওয়ার সুবিধাও রয়েছে এবং এর ব্যবহারকারীর তথ্য অভিধানের সদস্যের সাথে আরও বিশদভাবে ত্রুটিটি বর্ণনা করার উপায় সরবরাহ করে।
তবে সর্বোপরি, এনএসইরর ফেলে দেওয়া যায় না তাই এটি ত্রুটি পরিচালনার জন্য আরও প্র্যাক্টিভ পদ্ধতির উত্সাহ দেয়, অন্য ভাষাগুলির বিপরীতে যা কেবল গরম আলুটিকে আরও নিক্ষেপ করে এবং কল স্ট্যাকটি আরও ঠিক করে দেয় যে এটি কেবলমাত্র ব্যবহারকারীকে জানানো যেতে পারে এবং কোনও অর্থবহ উপায়ে পরিচালনা করা হয়নি (আপনি যদি ওওপির তথ্য গোপন করার বৃহত্তম নীতি অনুসরণ করেন তবে তা বিশ্বাস করেন না)।
রেফারেন্স লিঙ্ক: রেফারেন্স
"দ্য বিগ Nerd রাঞ্চ গাইড (চতুর্থ সংস্করণ)" থেকে আমি এটি শিখেছি:
@throw [NSException exceptionWithName:@"Something is not right exception"
reason:@"Can't perform this operation because of this or that"
userInfo:nil];
userInfo:nil
। :)
আমি বিশ্বাস করি স্বাভাবিক প্রোগ্রাম প্রবাহ নিয়ন্ত্রণ করতে আপনার কখনও ব্যতিক্রম ব্যবহার করা উচিত নয়। যখনই কিছু মান পছন্দসই মানের সাথে মেলে না, তখন ব্যতিক্রমগুলি ছুঁড়ে ফেলা উচিত।
উদাহরণস্বরূপ, যদি কোনও ফাংশন কোনও মান গ্রহণ করে এবং সেই মানটিকে কখনই শূন্য করার অনুমতি দেওয়া হয় না, তবে ব্যতিক্রম চালিয়ে নেওয়া ঠিক আছে তবে কিছু 'স্মার্ট' করার চেষ্টা করা ...
Ries
আপনি যদি কেবল কোনও প্রোগ্রামিং ত্রুটি নির্দেশ করে এমন একটি পরিস্থিতিতে নিজেকে খুঁজে পান এবং অ্যাপ্লিকেশনটি চালানো থেকে থামাতে চান তবেই আপনাকে ব্যতিক্রম ছুঁড়ে ফেলা উচিত। অতএব, ব্যতিক্রম ছোঁড়ার সর্বোত্তম উপায় হ'ল এনএসএসর্ট এবং এনএসপিআরমিটারসেটর ম্যাক্রোগুলি ব্যবহার করা এবং নিশ্চিত করে নিন যে এনএস_ব্লক_এএসআরটিএস সংজ্ঞাযুক্ত নয়।
মামলার জন্য নমুনা কোড: @ থ্রো ([এনএসইএসসেপশন ব্যতিক্রম নাম সহ: ...
- (void)parseError:(NSError *)error
completionBlock:(void (^)(NSString *error))completionBlock {
NSString *resultString = [NSString new];
@try {
NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
if(!errorData.bytes) {
@throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
}
NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
options:NSJSONReadingAllowFragments
error:&error];
resultString = dictFromData[@"someKey"];
...
} @catch (NSException *exception) {
NSLog( @"Caught Exception Name: %@", exception.name);
NSLog( @"Caught Exception Reason: %@", exception.reason );
resultString = exception.reason;
} @finally {
completionBlock(resultString);
}
}
ব্যবহার:
[self parseError:error completionBlock:^(NSString *error) {
NSLog(@"%@", error);
}];
আরেকটি আরও উন্নত ব্যবহারের ক্ষেত্রে:
- (void)parseError:(NSError *)error completionBlock:(void (^)(NSString *error))completionBlock {
NSString *resultString = [NSString new];
NSException* customNilException = [NSException exceptionWithName:@"NilException"
reason:@"object is nil"
userInfo:nil];
NSException* customNotNumberException = [NSException exceptionWithName:@"NotNumberException"
reason:@"object is not a NSNumber"
userInfo:nil];
@try {
NSData *errorData = [NSData dataWithData:error.userInfo[@"SomeKeyForData"]];
if(!errorData.bytes) {
@throw([NSException exceptionWithName:@"<Set Yours exc. name: > Test Exc" reason:@"<Describe reason: > Doesn't contain data" userInfo:nil]);
}
NSDictionary *dictFromData = [NSJSONSerialization JSONObjectWithData:errorData
options:NSJSONReadingAllowFragments
error:&error];
NSArray * array = dictFromData[@"someArrayKey"];
for (NSInteger i=0; i < array.count; i++) {
id resultString = array[i];
if (![resultString isKindOfClass:NSNumber.class]) {
[customNotNumberException raise]; // <====== HERE is just the same as: @throw customNotNumberException;
break;
} else if (!resultString){
@throw customNilException; // <======
break;
}
}
} @catch (SomeCustomException * sce) {
// most specific type
// handle exception ce
//...
} @catch (CustomException * ce) {
// most specific type
// handle exception ce
//...
} @catch (NSException *exception) {
// less specific type
// do whatever recovery is necessary at his level
//...
// rethrow the exception so it's handled at a higher level
@throw (SomeCustomException * customException);
} @finally {
// perform tasks necessary whether exception occurred or not
}
}
ব্যবসায়ের নিয়ম ব্যতিক্রমগুলি বোঝাতে এমনকি উদ্দেশ্য সিতে ব্যতিক্রমগুলি সাধারণত ব্যবহার না করার কোনও কারণ নেই। অ্যাপল বলতে পারেন এনএসআররার কে যত্ন করে তা ব্যবহার করতে পারেন। ওবজ সি প্রায় দীর্ঘ সময় ধরে ছিল এবং একসময় সমস্ত সি ++ নথিপত্র একই জিনিস বলেছিল। ব্যতিক্রম ছুঁড়ে ফেলা এবং ধরা কত ব্যয়বহুল তা বিবেচনা করার কারণ নয়, ব্যতিক্রমকালীন জীবনযাত্রা অত্যন্ত সংক্ষিপ্ত এবং ... এটি স্বাভাবিক প্রবাহের জন্য একটি এক্সেসপশন। আমি জীবনে কখনও কাউকে বলতে কখনও শুনিনি, মানুষ যে ব্যতিক্রমটি ছুঁড়ে ফেলা এবং ধরা দিতে দীর্ঘ সময় নিয়েছিল।
এছাড়াও, এমন লোকেরা আছেন যা মনে করেন যে উদ্দেশ্য সি নিজেই খুব ব্যয়বহুল এবং পরিবর্তে সি বা সি ++ তে কোড। তাই সর্বদা এনএসইরর ব্যবহারের কথাটি অজ্ঞাত-জ্ঞাত এবং ভৌতিক।
তবে এই থ্রেডের প্রশ্নের উত্তর এখনও পাওয়া যায় নি একটি ব্যতিক্রম ছড়িয়ে দেওয়ার সর্বোত্তম উপায় কী। এনএসইররর ফেরার উপায়গুলি সুস্পষ্ট।
তাই কি এটি: [এনএসইসেপশন উত্থাপন: ... @ থ্রো [[এনএসইসেপশন বরাদ্দ] আর্ট উইথনাম .... বা @ থ্রো [[মাই কাস্টম এক্সেপশন ...?
আমি এখানে চেক / চেক করা নিয়ম উপরের চেয়ে কিছুটা আলাদাভাবে ব্যবহার করি।
(এখানে জাভা রূপক ব্যবহার করে) চেক করা / চেক করা না হওয়াতে আসল পার্থক্যটি গুরুত্বপূর্ণ -> আপনি ব্যতিক্রম থেকে পুনরুদ্ধার করতে পারবেন কিনা। এবং পুনরুদ্ধার করার অর্থ আমি কেবল ক্র্যাশ নয়।
সুতরাং আমি পুনরুদ্ধারযোগ্য ব্যতিক্রমগুলির জন্য @ থ্রো সহ কাস্টম ব্যতিক্রম ক্লাসগুলি ব্যবহার করি, কারণ এর সম্ভবত আমার একাধিক @ ক্যাচ ব্লকগুলিতে নির্দিষ্ট ধরণের ব্যর্থতার সন্ধানে কিছু অ্যাপ পদ্ধতি থাকবে। উদাহরণস্বরূপ, যদি আমার অ্যাপ্লিকেশনটি এটিএম মেশিন হয় তবে আমার কাছে "উইথড্রওয়ারালেক্সটেক্সটেক্সসালেন্স ব্যালেন্সএক্সসেপশন" এর জন্য একটি @ ক্যাচ ব্লক থাকবে।
আমি এনএসইসিপশন ব্যবহার করি: রানটাইম ব্যতিক্রমগুলির জন্য উত্থাপন করুন যেহেতু উচ্চতর স্তরে এটি ধরতে এবং লগ ইন করা ব্যতীত আমার ব্যতিক্রম থেকে পুনরুদ্ধার করার কোনও উপায় নেই। এবং এটির জন্য একটি কাস্টম ক্লাস তৈরির কোনও অর্থ নেই।
যাইহোক আমি যা করি তা ঠিক করে দেয় তবে এর চেয়ে ভালতর, অনুরূপ মত প্রকাশের উপায় থাকলে আমিও জানতে চাই। আমার নিজের কোডে, যেহেতু আমি অনেক আগে অনেক আগে হেলাকে কোডিং করা বন্ধ করে দিয়েছি, আমি কোনও এপিআই দ্বারা পাস হয়ে গেলেও আমি কখনই কোনও এনএসইরর ফিরে পাই না।
@throw([NSException exceptionWith…])
আরও বেশি সংক্ষিপ্ত হিসাবে পদ্ধতির কাছে প্রয়োগ হিসাবে এই উপায়ে পছন্দ করি ।