ভেরিয়েবলটি নাল-চেক করার জন্য কেন একটি preচ্ছিক অগ্রাধিকার ব্যবহার করা হচ্ছে?


25

দুটি কোডের উদাহরণ নিন:

if(optional.isPresent()) {
    //do your thing
}

if(variable != null) {
    //do your thing
}

যতদূর আমি সবচেয়ে সুস্পষ্ট পার্থক্যটি বলতে পারি ptionচ্ছিক একটি অতিরিক্ত অবজেক্ট তৈরি করা প্রয়োজন।

তবে, অনেকে বিকল্পগুলি অবলম্বন করতে শুরু করেছেন। নাল চেক বনাম বিকল্পগুলি ব্যবহার করার সুবিধা কী?


4
আপনি প্রায়শই ইস্প্রেসেট ব্যবহার করতে চান না, আপনার সাধারণত ইফপ্রেসেন্ট বা মানচিত্র
জে কে

6
@jk। কারণ ifবিবৃতি খুব এ গত এক দশকে, এবং সবাই এখন একসংখ্যা বিমূর্ত এবং lambdas ব্যবহার করছে।
ব্যবহারকারী 253751

2
@ মিমিবিস আমি একবার এই বিষয় নিয়ে অন্য একজন ব্যবহারকারীর সাথে দীর্ঘ আলোচনা করেছি। মুল বক্তব্যটি হ'ল if(x.isPresent) fails_on_null(x.get)আপনার মধ্যে টাইপ সিস্টেমটি প্রস্থান করে এবং গ্যারান্টিটি রাখতে হবে যে শর্ত এবং ফাংশন কলের মধ্যে (স্বীকারোক্তিপূর্ণ সংক্ষিপ্ত) দূরত্বের পরে কোডটি "আপনার মাথার মধ্যে" ভঙ্গ হবে না। ইন optional.ifPresent(fails_on_null)টাইপ সিস্টেম আপনার জন্য এই গ্যারান্টি তোলে, এবং আপনি চিন্তা করতে হবে না।
ziggystar

1
Optional.ifPresent(এবং বিভিন্ন অন্যান্য জাভা কনস্ট্রাক্টস) ব্যবহার করে জাভার প্রধান ত্রুটি হ'ল আপনি কেবল কার্যকরভাবে চূড়ান্ত পরিবর্তনশীলগুলি সংশোধন করতে পারবেন এবং চেক করা ব্যতিক্রমগুলি ছুঁড়ে ফেলতে পারবেন না। ifPresentদুর্ভাগ্যক্রমে এটি প্রায়শই এড়াতে যথেষ্ট কারণ ।
মাইক

উত্তর:


19

Optionalস্মরণ থাকুক বা না থাকুক একটি প্রদত্ত রেফারেন্স হতে পারে: কাজ যে আপনি অন্যথায় আপনার মাথা সমস্ত যা করতে হবে চাই করছেন জন্য টাইপ সিস্টেম harnesses null। এটা ভাল. এটি সর্বদা স্মার্ট হ'ল সংকলকটি বোরিং ড্রু ওয়ার্কটি পরিচালনা করতে দেয় এবং সৃজনশীল, আকর্ষণীয় কাজের জন্য মানুষের চিন্তাভাবনা সংরক্ষণ করে।

ছাড়া Optional, আপনার কোডের প্রতিটি রেফারেন্স একটি বিস্ফোরিত বোমার মতো। এটি অ্যাক্সেস করা কার্যকর কিছু করতে পারে, বা অন্যথায় এটি কোনও ব্যতিক্রম ব্যতীত আপনার প্রোগ্রামটি শেষ করে দিতে পারে।

Ptionচ্ছিক এবং ছাড়াই null, একটি সাধারণ রেফারেন্সের প্রতিটি অ্যাক্সেস সফল হয় এবং unচ্ছিক প্রতিটি রেফারেন্স সফল না হয়ে থাকে যদি না এটি সেট না করে থাকে এবং আপনি এটি পরীক্ষা করতে ব্যর্থ হন। এটি রক্ষণাবেক্ষণের বিশাল জয় is

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


যেহেতু আপনার উত্তরটি শীর্ষস্থানীয়, ভবিষ্যতে যে কেউ এটি পড়বে (আমার উত্তর দেখুন)
উইলিয়াম ডান

বেশিরভাগ আধুনিক ভাষাগুলি অ-প্র্রজনীয় প্রকারগুলি সরবরাহ করে, কোটলিন, টাইপসক্রিপ্ট, আফাইক AI
জেন

5
আইএমও এটি একটি @ ননাল টীকা সহ আরও ভালভাবে পরিচালনা করা হয়। আপনাকে Optionalকেবল মূল্য স্মরণ করিয়ে দেওয়ার জন্য ব্যবহার করার কোনও কারণ নেই
হিলিকাস

18

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

optionalআপনার উদাহরণ কোড থেকে আপনার পরিবর্তনশীল কিনা তা বিবেচনা করুন , তাহলে আপনাকে দুটি অতিরিক্ত পদক্ষেপ করতে হয়েছিল যা প্রত্যেকে সম্ভাব্য ব্যর্থ হতে পারে। পথে যদি কোনও পদক্ষেপ ব্যর্থ হয়, আপনি পরিবর্তে একটি ডিফল্ট মান ফিরিয়ে দিতে চান। Optionalsসঠিকভাবে ব্যবহার করে , আপনি এরকম কিছু দিয়ে শেষ করেছেন:

return optional.flatMap(x -> x.anotherOptionalStep())
               .flatMap(x -> x.yetAnotherOptionalStep())
               .orElse(defaultValue);

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

দ্রষ্টব্য আমি isPresentএকবার কল করি নি , যা ব্যবহারের সময় আপনার কোড গন্ধ হিসাবে ভেবে দেখা উচিত Optionals। এর অর্থ এই নয় যে আপনার কখনই ব্যবহার করা উচিত নয়isPresent , কেবল এটির চেয়ে আরও ভাল উপায় আছে কিনা তা দেখার জন্য আপনার যে কোনও কোডের ভারী তদন্ত করা উচিত। অন্যথায়, আপনি ঠিক বলেছেন, আপনি কেবলমাত্র ব্যবহারের মাধ্যমে প্রান্তিক প্রকারের সুরক্ষা সুবিধা পাচ্ছেন null

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


10

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

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


4

আমাকে যদি আপনি একটি উদাহরণ দিতে:

class UserRepository {
     User findById(long id);
}

এটি পুরোপুরি স্পষ্ট যে এই পদ্ধতিটি কীসের উদ্দেশ্যে। কিন্তু যদি ভাণ্ডারটিতে প্রদত্ত আইডি সহ ব্যবহারকারী না থাকে তবে কি হবে? এটি একটি ব্যতিক্রম নিক্ষেপ করতে পারে বা এটি শূন্য ফিরে আসতে পারে?

দ্বিতীয় উদাহরণ:

class UserRepository {
     Optional<User> findById(long id);
}

এখন, প্রদত্ত আইডি সহ কোনও ব্যবহারকারী না থাকলে এখানে কী হবে? ঠিক আছে, আপনি Optional.abmitted () উদাহরণ পাবেন এবং আপনি এটি Optional.isPstream () দিয়ে পরীক্ষা করতে পারেন। Contractচ্ছিক সহ পদ্ধতি স্বাক্ষর এর চুক্তি সম্পর্কে আরও সুস্পষ্ট। এটি অবিলম্বে পরিষ্কার, পদ্ধতিটি কীভাবে আচরণ করা অনুমিত হয়।

ক্লায়েন্ট কোড পড়ার সময় এর একটি সুবিধাও রয়েছে:

User user = userRepository.findById(userId).get();

আমি তাত্ক্ষণিক কোড গন্ধ হিসাবে .get () দেখতে আমার চোখ প্রশিক্ষিত করেছি। এর অর্থ হ'ল ক্লায়েন্ট উদ্দেশ্যমূলকভাবে চুক্তিভুক্ত পদ্ধতির চুক্তিকে অগ্রাহ্য করে। Ptionচ্ছিক ছাড়া এটি দেখতে অনেক সহজ, কারণ এই ক্ষেত্রে আপনি অবিলম্বে অবগত নন যে নামক পদ্ধতির চুক্তিটি রয়েছে (এটি তার পরিবর্তে নਾਲকে অনুমতি দেয় কিনা তা নয়) তাই আপনাকে প্রথমে এটি পরীক্ষা করা উচিত।

Conventionচ্ছিকটি কনভেনশনটির সাথে ব্যবহার করা হয় যে রিটার্ন টাইপের পদ্ধতিগুলি nচ্ছিক কখনই বাতিল হয় না এবং সাধারণত (কম শক্তিশালী) কনভেনশনের সাথেও methodচ্ছিক রিটার্ন টাইপ ব্যতীত পদ্ধতিটি কখনই শূন্য হয় না (তবে এটি @ নননল, @ নটনল বা অনুরূপ দিয়ে টিকিয়ে দেওয়া আরও ভাল) ।


3

একটি Optional<T>আপনাকে আপনার পদ্ধতির বৈধ প্রতিক্রিয়া / রিটার্ন মান হিসাবে "ব্যর্থতা" বা "কোনও ফলাফল" পেতে দেয় (চিন্তা করুন, উদাহরণস্বরূপ, একটি ডাটাবেস অনুসন্ধানের)। একটি ব্যবহার Optionalপরিবর্তে ব্যবহার করার nullব্যর্থতা ইঙ্গিত / না ফলাফলের কিছু সুফল রয়েছে:

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

দুর্ভাগ্যক্রমে, এটি nullকোডে চেকগুলির প্রয়োজনীয়তাটিকে পুরোপুরি সরিয়ে দেয় না কারণ এটি Optionalএখনও অবজেক্টের হতে পারে null


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

আমি দৃ strongly়ভাবে একমত না। Ptionচ্ছিক.অম্পটি () আমার মতে ব্যর্থতা বা অ-অস্তিত্ব প্রদর্শন করার দুর্দান্ত উপায়।
কিংবদন্তি লেন্থথ

@ লেজেন্ডলেন্থ, ব্যর্থতার ক্ষেত্রে অবশ্যই আমাকে দৃ strongly়ভাবে একমত হতে হবে না। যদি কোনও ফাংশন ব্যর্থ হয় তবে এটি কেবল একটি খালি নয়, "আমি ব্যর্থ হয়েছিলাম"
উইনস্টন ইওয়ার্ট

দুঃখিত আমি সম্মত, একটি অনুসন্ধানের সময় 'x' নামের কোনও কর্মচারী খুঁজে না পাওয়া হিসাবে আমার অর্থ 'প্রত্যাশিত ব্যর্থতা'।
কিংবদন্তি

3

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

opTr.ifPresent(tr -> transactions.put(tr.getTxid(), tr));

2

নিম্নলিখিত পদ্ধতিটি বিবেচনা করুন:

void dance(Person partner)

এখন কিছু কলিং কোড দেখুন:

dance(null);

এটি অন্য কোথাও ক্র্যাশ ট্র্যাক করা সম্ভাব্যভাবে সমস্যার কারণ, শূন্যতার danceপ্রত্যাশা করে না।

dance(optionalPerson)

এটি একটি সংকলন ত্রুটির কারণ, কারণ নাচ একটি Personনা একটি আশা করেছিলOptional<Person>

dance(optionalPerson.get())

যদি আমার কোনও ব্যক্তি না থাকে তবে এটি এই লাইনে একটি ব্যতিক্রম ঘটায়, যেখানে আমি অবৈধভাবে Optional<Person>ব্যক্তিকে রূপান্তরিত করার চেষ্টা করেছি । মূলটি হ'ল শূন্যতা পেরিয়ে যাওয়ার পরিবর্তে, প্রোগ্রামটির অন্য কোনও স্থান নয়, এখানে চিহ্নগুলি বাদে।

এগুলি একসাথে রাখার জন্য: alচ্ছিক অপব্যবহারের ফলে সমস্যাগুলি সনাক্ত করা সহজতর হয়, নালকে অপব্যবহার করলে সমস্যাগুলি ট্র্যাক করা সহজ হয়।


1
যদি Optional.get()আপনার কোডটি কলটিযুক্তভাবে লিখিত হয় তখন আপনি যদি ব্যতিক্রম ছুঁড়ে মারছেন - আপনি প্রায় কখনও অপশনাল.জেটে কল করবেন না Optional.isPresent()(প্রথমে ওপিতে নির্দেশিত হিসাবে) বা আপনি লিখতে পারেন optionalPersion.ifPresent(myObj::dance)
ক্রিস কুপার

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

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

@ লেজেন্ডলেন্থ, আমার অভিজ্ঞতা হল যে ৯৫% কেস NUL কোথা থেকে এসেছে তা সনাক্ত করার জন্য সত্যই সহজেই সন্ধানযোগ্য। বাকি 5% তবে ট্র্যাকডাউন করা অত্যন্ত কঠিন।
উইনস্টন ইওয়ার্ট

-1

অবজেক্টিভ-সি-তে, সমস্ত বস্তুর উল্লেখগুলি alচ্ছিক। এই কারণে আপনার পোস্ট করা কোডটি নির্বোধ।

if (variable != nil) {
    [variable doThing];
}

উপরের মত কোডটি অবজেক্টিভ-সি-তে শোনা যায় না। পরিবর্তে, প্রোগ্রামারটি কেবল এটি করবে:

[variable doThing];

যদি variableকোনও মান থাকে, তবে এটিতে doThingডাকা হবে। না হলে কোনও ক্ষতি নেই। প্রোগ্রামটি এটিকে কোনও অপ-বিকল্প হিসাবে বিবেচনা করবে এবং চলমান চালিয়ে যাবে।

এটি বিকল্পগুলির আসল সুবিধা। আপনাকে আপনার কোডটি দিয়ে লিটার করতে হবে না if (obj != nil)


নিছক চুপচাপ ব্যর্থ হওয়া কি এটির এক রূপ নয়? কিছু ক্ষেত্রে আপনি যত্ন নিতে পারেন যে মানটি শূন্য, এবং এটি সম্পর্কে কিছু করতে চান।
কিংবদন্তি লেন্থথ

-3

যদি (alচ্ছিক.আইসপ্রেসড ()) {

সুস্পষ্ট সমস্যা এখানে যে যদি "ঐচ্ছিক" সত্যিই হয় অনুপস্থিত (অর্থাত নাল থাকে) তাহলে আপনার কোড একটি NullReferenceException (বা অনুরূপ) সঙ্গে উড়িয়ে দেওয়ার একটি নাল অবজেক্ট রেফারেন্স কোন পদ্ধতি কল করতে চাইছেন যাচ্ছে!

আপনি একটি স্থিতিশীল, সহায়ক-শ্রেণীর পদ্ধতি লিখতে চাইতে পারেন যা কোনও প্রদত্ত বস্তুর ধরণের নাল-নেস নির্ধারণ করে, এরকম কিছু:

function isNull( object o ) 
{
   return ( null == o ); 
}

if ( isNull( optional ) ) ... 

বা, সম্ভবত, আরও কার্যকরভাবে:

function isNotNull( object o ) 
{
   return ( null != o ); 
}

if ( isNotNull( optional ) ) ... 

তবে এগুলি কি আসলেই আসলটির চেয়ে আরও বেশি পঠনযোগ্য / বোধগম্য / রক্ষণাবেক্ষণযোগ্য?

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