Javaচ্ছিক নাল পয়েন্টার চেকের পরিবর্তে জাভা 8+ এ inচ্ছিক কেন ব্যবহার করবেন?


110

আমরা সম্প্রতি জাভা ৮ এ চলে এসেছি Now এখন, আমি দেখতে পাচ্ছি অ্যাপ্লিকেশনগুলি Optionalবস্তুতে ভরা।

জাভা 8 এর আগে (স্টাইল 1)

Employee employee = employeeServive.getEmployee();

if(employee!=null){
    System.out.println(employee.getId());
}

জাভা 8 পরে (স্টাইল 2)

Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee());
if(employeeOptional.isPresent()){
    Employee employee = employeeOptional.get();
    System.out.println(employee.getId());
}

আমি Optional<Employee> employeeOptional = employeeService.getEmployee();যখন পরিষেবা নিজেই alচ্ছিক প্রত্যাবর্তন করি তখন এর কোনও অতিরিক্ত মূল্য আমি দেখিনা:

একটি জাভা 6 ব্যাকগ্রাউন্ড থেকে আগত, আমি স্টাইল 1 দেখতে আরও স্পষ্ট এবং কোডের কম লাইনের সাথে দেখছি। আমি এখানে অনুপস্থিত কোন বাস্তব সুবিধা আছে?

সমস্ত উত্তর থেকে বোঝা এবং ব্লগে আরও গবেষণা থেকে একীভূত



28
ইশ! employeeOptional.isPresent()বিকল্প ধরণের পয়েন্টটি পুরোপুরি অনুপস্থিত বলে মনে হচ্ছে। @ মাইকপার্টরিজ এর মন্তব্য অনুসারে, এটি প্রস্তাবিত বা প্রতিমা নয়। কোনও বিকল্প টাইপ কিছু বা কিছুই হ'ল কিনা তা স্পষ্টভাবে যাচাই করা । আপনার মনে হয় কেবল mapবা flatMapতাদের উপরের ।
অ্যান্ড্রেস এফ

7
দেখুন একটি স্ট্যাক ওভারফ্লো উপর উত্তরOptional দ্বারা ব্রায়ান Goetz , জাভা ভাষা স্থপতি ওরাকল করেন।
বেসিল বোর্কে

6
"সেরা অনুশীলনের" নামে আপনি যখন আপনার মস্তিষ্ক বন্ধ করেন তখন এটি ঘটে happens
ইমিগ্রিস

9
এটি alচ্ছিকের মোটামুটি দুর্বল ব্যবহার তবে এর সুবিধাও রয়েছে। নালগুলির সাথে সবকিছু নাল হতে পারে, তাই আপনাকে নিয়মিত চেক করা দরকার, alচ্ছিক কলগুলি বলে যে এই নির্দিষ্ট চলকটি অনুপস্থিত সম্ভবত, আপনি এটি পরীক্ষা করে নিন
রিচার্ড টিঙ্গল

উত্তর:


108

পুরো সুবিধাটি দেখতে স্টাইল 2 জাভা 8 তে যথেষ্ট যাচ্ছে না। আপনি মোটেও চান না if ... use। দেখুন ওরাকল এর উদাহরণ । তাদের পরামর্শ গ্রহণ, আমরা পেতে:

স্টাইল 3

// Changed EmployeeServive to return an optional, no more nulls!
Optional<Employee> employee = employeeServive.getEmployee();
employee.ifPresent(e -> System.out.println(e.getId()));

বা আরও দীর্ঘ স্নিপেট

Optional<Employee> employee = employeeServive.getEmployee();
// Sometimes an Employee has forgotten to write an up-to-date timesheet
Optional<Timesheet> timesheet = employee.flatMap(Employee::askForCurrentTimesheet); 
// We don't want to do the heavyweight action of creating a new estimate if it will just be discarded
client.bill(timesheet.orElseGet(EstimatedTimesheet::new));

19
প্রকৃতপক্ষে আমরা ইস্প্রেসির বেশিরভাগ ব্যবহার (কোড পর্যালোচনা দ্বারা ধরা)
জে কে

10
@jk। সত্যই, যদি ওভারলোড হত তবে void ifPresent(Consumer<T>, Runnable)আমি সম্পূর্ণ নিষেধাজ্ঞার পক্ষে যুক্তি দিতাম isPresentএবংget
কালেথ

10
@ ক্যালথ: আপনি জাভা 9 এর জন্য আগ্রহী হতে পারেন ifPresentOrElse(Consumer<? super T>, Runnable)
wchargin

9
আমি জাভা one টির তুলনায় এই জাভা 8 স্টাইলে একটি অপূর্ণতা পেয়েছি: এটি কোড কভারেজ সরঞ্জামগুলিকে বোকা বানাবে। যদি বিবৃতি দিয়ে এটি প্রদর্শিত হয় আপনি যখন এখানে একটি শাখা মিস করবেন না।
থিয়েরি

14
@ অ্যারন "কোড পঠনযোগ্যতা হ্রাস করে"। কোন অংশটি পড়ার ক্ষমতা হ্রাস করে? উদ্দেশ্য যুক্তির চেয়ে "আমি সর্বদা এটি আলাদাভাবে করেছি এবং আমি আমার অভ্যাস পরিবর্তন করতে চাই না" এর মতো আরও শোনাচ্ছে।
ভু

47

যদি আপনি Optionalকোনও পুরনো এপিআইয়ের মধ্যে "সামঞ্জস্য" স্তর হিসাবে ব্যবহার করেন যা এখনও ফিরে আসতে nullপারে তবে সর্বশেষ পর্যায়ে (খালি নয়) alচ্ছিকটি তৈরি করতে সহায়ক হতে পারে আপনি নিশ্চিত যে আপনার কাছে কিছু আছে। যেমন, আপনি যেখানে লিখেছেন:

Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee());
if(employeeOptional.isPresent()){
    Employee employeeOptional= employeeOptional.get();
    System.out.println(employee.getId());
}

আমি পছন্দ করতাম:

Optional.of(employeeService)                 // definitely have the service
        .map(EmployeeService::getEmployee)   // getEmployee() might return null
        .map(Employee::getId)                // get ID from employee if there is one
        .ifPresent(System.out::println);     // and if there is an ID, print it

বিন্দু পথ পাবো না জানি একটি অ-নাল কর্মচারী আছে যে সেবা , তাই আপনি একটি আপ যে মোড়ানো পারেন Optionalসঙ্গে Optional.of()। তারপরে, আপনি যখন ফোন করবেন তখন আপনি getEmployee()কোনও কর্মী পেতে পারেন বা নাও পেতে পারেন। সেই কর্মচারীর আইডি থাকতে পারে (বা, সম্ভবত, নাও থাকতে পারে)। তারপরে, আপনি যদি কোনও আইডি দিয়ে শেষ করেন, আপনি এটি মুদ্রণ করতে চান।

এই কোডটিতে কোনও নাল, উপস্থিতি ইত্যাদি স্পষ্টভাবে পরীক্ষা করার দরকার নেই ।


4
(...).ifPresent(aMethod)ওভার ব্যবহার করে if((...).isPresent()) { aMethod(...); }কী লাভ ? প্রায় একই ক্রিয়াকলাপটি করার জন্য এটি অন্য একটি বাক্য গঠন বলে মনে হচ্ছে।
Ruslan

2
@ রুসালান যখনই আপনার কাছে ইতিমধ্যে একটি সাধারণ সমাধান রয়েছে যা সমস্ত ক্ষেত্রে সমানভাবে কার্যকরভাবে কাজ করে তবে একটি নির্দিষ্ট কলের জন্য একটি বিশেষ সিনট্যাক্স কেন ব্যবহার করবেন? আমরা ঠিক এখানে মানচিত্র এবং সহ থেকে একই ধারণা প্রয়োগ করছি।
ভু

1
@ রুসলান ... একটি এপিআই খালি সংগ্রহ বা অ্যারের পরিবর্তে নাল ফেরায়। উদাহরণস্বরূপ, আপনি এর মতো কিছু করতে পারেন (ধরে নিলেন একটি পিতামাতার ক্লাস ধরে যার জন্য getChildren () বাচ্চাদের একটি সেট প্রদান করে, বা কোনও শিশু না থাকলে নাল): Set<Children> children = Optional.of(parent).map(Parent::getChildren).orElseGet(Collections::emptySet); এখন আমি childrenঅভিন্ন প্রক্রিয়া করতে পারি , যেমন children.forEach(relative::sendGift);,। ঐ এমনকি মিলিত করা যেতে পারে: Optional.of(parent).map(Parent::getChildren).orElseGet(Collections::emptySet).forEach(relative::sendGift);। নাল চেকিং ইত্যাদির সমস্ত বয়লারপ্লেট ...
জোশুয়া টেলর

1
@ রুসলান ... স্ট্যান্ডার্ড লাইব্রেরিতে চেষ্টা করা এবং সত্য কোডের জন্য প্রেরণ করা হয়েছে। এটি প্রোগ্রামার হিসাবে আমাকে কোড, পরীক্ষা, ডিবাগ ইত্যাদির কোডের পরিমাণ হ্রাস করে
জোশুয়া টেলর

1
খুশি আমি সুইফট ব্যবহার করছি। if কর্মচারী = কর্মচারী.সেম্পোর.ইম্প্লোই {মুদ্রণ (কর্মচারী.আইডি); }
gnasher729

23

Optionalএকটি একক মানের থাকার কোনও যোগ মানের পরে নেই । আপনি যেমনটি দেখেছেন, এটি nullউপস্থিতির জন্য একটি চেকের পরিবর্তে একটি চেকের পরিবর্তে ।

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


24
সংগ্রহ / স্ট্রিম বাদে, APIচ্ছিক এপিআইগুলিকে আরও স্ব-ডকুমেন্টিং তৈরি করার জন্য দুর্দান্ত, যেমন Employee getEmployee()বনাম Optional<Employee> getEmployee()। প্রযুক্তিগতভাবে উভয়ই ফিরে আসতে পারলেও nullতাদের মধ্যে একটির কারণে সমস্যা হওয়ার সম্ভাবনা অনেক বেশি।
সোমবার

16
একক মানের alচ্ছিকতে প্রচুর মান রয়েছে। .map()সমস্ত পথে নাল পরীক্ষা না করেই সক্ষম হওয়া দুর্দান্ত। যেমন Optional.of(service).map(Service::getEmployee).map(Employee::getId).ifPresent(this::submitIdForReview);,।
জোশুয়া টেলর

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

3
@ জোশুয়া টেইলর সত্যই, এই অভিব্যক্তির তুলনায় , আমি পুরানো ধরণের চেক পছন্দ করি null
কিলিয়ান পাথ

2
এমনকি একক মান সহ ptionচ্ছিকের আরও একটি বড় সুবিধা হ'ল আপনার যখন করা উচিত তখন আপনি নাল পরীক্ষা করতে ভুলে যেতে পারবেন না। অন্যথায় চেকটি ভুলে যাওয়া এবং নালপয়েন্টার এক্সেপশন দিয়ে শেষ করা খুব সহজ ...
সান বার্টন

17

যতক্ষণ আপনি Optionalঠিক অভিনব এপিআইয়ের মতো ব্যবহার করেন isNotNull(), ততক্ষণ হ্যাঁ, আপনি কেবলমাত্র পরীক্ষা করে কোনও পার্থক্য খুঁজে পাবেন না null

আপনি যে জিনিসগুলি ব্যবহার করা উচিত নয় Optionalজন্য

Optionalএকটি মান উপস্থিতি যাচাই করার জন্য ব্যবহার করা খারাপ কোড ™:

// BAD CODE ™ --  just check getEmployee() != null  
Optional<Employee> employeeOptional =  Optional.ofNullable(employeeService.getEmployee());  
if(employeeOptional.isPresent()) {  
    Employee employee = employeeOptional.get();  
    System.out.println(employee.getId());
}  

আপনার যে জিনিসগুলির Optionalজন্য ব্যবহার করা উচিত

নাল-রিটার্নিং এপিআই পদ্ধতি ব্যবহার করার সময় যখন প্রয়োজন হয় তখন একটি উত্পাদন করে একটি মান উপস্থিত না করা থেকে বিরত থাকুন:

Employee employee = Optional.ofNullable(employeeService.getEmployee())
                            .orElseGet(Employee::new);
System.out.println(employee.getId());

অথবা, নতুন কর্মচারী তৈরি করা যদি খুব ব্যয়বহুল হয়:

Optional<Employee> employee = Optional.ofNullable(employeeService.getEmployee());
System.out.println(employee.map(Employee::getId).orElse("No employee found"));

এছাড়াও, প্রত্যেককে সচেতন করে তুলুন যে আপনার পদ্ধতিগুলি কোনও মান ফেরত দিতে পারে না (যদি কোনও কারণেই হয় তবে আপনি উপরের মতো কোনও ডিফল্ট মান ফিরিয়ে দিতে পারবেন না):

// Your code without Optional
public Employee getEmployee() {
    return someCondition ? null : someEmployee;
}
// Someone else's code
Employee employee = getEmployee(); // compiler doesn't complain
// employee.get...() -> NPE awaiting to happen, devs criticizing your code

// Your code with Optional
public Optional<Employee> getEmployee() {
    return someCondition ? Optional.empty() : Optional.of(someEmployee);
}
// Someone else's code
Employee employee = getEmployee(); // compiler complains about incompatible types
// Now devs either declare Optional<Employee>, or just do employee = getEmployee().get(), but do so consciously -- not your fault.

এবং পরিশেষে, সমস্ত স্ট্রিমের মতো পদ্ধতি রয়েছে যা ইতিমধ্যে অন্যান্য উত্তরে ব্যাখ্যা করা হয়েছে, যদিও সেগুলি সত্যই আপনি ব্যবহার করার সিদ্ধান্ত নিচ্ছেন Optionalনা Optionalতবে অন্য কারও সরবরাহকৃত ব্যবহারটি ব্যবহার করছেন ।


1
পছন্দ করুন / আর / জাভা নিয়ে আমাদের এই বিতর্ক ছিল, এবং আমি বলেছিলাম : missed আমি Optionalএকটি মিস করা সুযোগ হিসাবে দেখছি । "এখানে, এই নতুন আছে Optionalজিনিস আমি তাই তৈরি আপনি নাল মান পরীক্ষা করার জন্য বাধ্য ওহ, এবং উপায় দ্বারা ... আমি একটি এখনো যোগ করেনি। get()এটি পদ্ধতি যাতে আপনি আসলে কিছু জন্য চেক করতে হবে না;);)" । (...) Optionalএকটি "এই শূন্য হতে পারে" নিয়ন প্রতীক হিসেবে চমৎকার, কিন্তু তার বিষয়ে জোর গলায় অস্তিত্ব get()পদ্ধতি অচল এটা » । তবে ওপি ব্যবহারের কারণ জিজ্ঞাসা করছে Optional, এর বিরুদ্ধে কারণ বা ডিজাইনের ত্রুটিগুলি নয়।
ওয়ালেন

1
Employee employee = Optional.ofNullable(employeeService.getEmployee());আপনার তৃতীয় স্নিপেটে, টাইপটি হওয়া উচিত নয় Optional<Employee>?
চার্লি হার্ডিং

2
@ ইমিবিস কীভাবে পঙ্গু হয়েছে? ব্যবহারের প্রধান কারণ getহ'ল যদি আপনাকে কিছু লিগ্যাসি কোডের সাথে ইন্টারেক্ট করতে হয়। নতুন কোডটি ব্যবহারের জন্য আমি অনেকগুলি বৈধ কারণ সম্পর্কে ভাবতে পারি না get। লিগ্যাসি কোডের সাথে আলাপচারিত করার সময় এটির প্রায়শই বিকল্প নেই বলে উল্লেখ করা হয়েছিল, তবে এখনও ওয়ালেনের একটি বিন্দু রয়েছে যে getশুরুর দিকে খারাপ কোড লিখতে শুরু করে।
ভু

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

2
@ ভু Mapএমন একটি উদাহরণ যার সাথে সবাই পরিচিত। অবশ্যই Map.getপিছনের দিকের সামঞ্জস্যের কারণে তারা রিটার্নটিকে একটি ptionচ্ছিক করতে পারে না তবে আপনি সহজেই অন্য কোনও মানচিত্রের মতো শ্রেণীর কল্পনা করতে পারেন যাতে এই ধরণের সামঞ্জস্যের সীমাবদ্ধতা থাকবে না। বলুন class UserRepository {Optional<User> getUserDetails(int userID) {...}}। এখন আপনি লগ ইন ব্যবহারকারীর বিশদটি পেতে চান এবং আপনি জানেন যে সেগুলি বিদ্যমান কারণ তারা লগ ইন করতে পেরেছিল এবং আপনার সিস্টেম কখনও ব্যবহারকারীদের মুছে না। সুতরাং আপনি কি theUserRepository.getUserDetails(loggedInUserID).get()
ইমিগ্রিস

12

Developচ্ছিক ব্যবহারের ক্ষেত্রে আমার মূল বক্তব্যটি স্পষ্ট থাকে যখন বিকাশকারীকে ফাংশন রিটার্নের মান হয় কিনা তা পরীক্ষা করা দরকার।

//service 1
Optional<Employee> employeeOptional = employeeService.getEmployee();
if(employeeOptional.isPresent()){
    Employee employeeOptional= employeeOptional.get();
    System.out.println(employee.getId());
}

//service 2
Employee employee = employeeService.getEmployeeXTPO();
System.out.println(employee.getId());

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

3
ঠিক আছে, "পুরানো কোড" সমস্যা রয়েছে যেখানে জিনিসগুলি এখনও শূন্য হতে পারে ... তবে হ্যাঁ, স্বাক্ষর থেকে বলতে সক্ষম হওয়া দুর্দান্ত।
হাকন লাটভিট

5
হ্যাঁ এটি অবশ্যই ভাষাগুলিতে আরও ভাল কাজ করে যেখানে <চ্ছিক <T> হ'ল একমাত্র উপায় যে কোনও মান অনুপস্থিত হতে পারে, অর্থাত নাল পিটিআর ছাড়াই ভাষা।
dureuill

8

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

এটি আপনাকে নিখুঁতভাবে সুসংগত কোড লিখতে পরিচালিত করেছে যা পুরোপুরি যুক্তিসঙ্গত বলে মনে হয় তবে আপনি দুর্বল যোজন প্রলোভনগুলির দ্বারা প্রবৃত্ত হয়েছিলেন যা পেয়ে যায় এবং প্রকাশিত হয়।

অবশ্যই প্রশ্নটি "হয়ে ওঠে কেন এবং সেখানে উপস্থিত হয় কেন?"

এখানকার অনেক লোক যে জিনিসটি মিস করেন তা হ'ল ইজপ্রেসড () হ'ল এটি এমন কিছু নয় যা পুরোপুরিভাবে গোশত-ডার্ন লম্বা লম্বা কীভাবে এবং কীভাবে কার্যকরী জিনিস পছন্দ করে তা নিয়ে লোকেরা লিখেছেন নতুন কোডের জন্য।

তবে এটি আমাদের কয়েকটি (দুটি) ভাল, দুর্দান্ত, গ্ল্যামারাস (?) সুবিধা দেয়:

  • এটি নতুন বৈশিষ্ট্যগুলি ব্যবহার করার জন্য উত্তরাধিকার কোডের উত্তরণকে সহজ করে।
  • এটি ptionচ্ছিকের শেখার কার্ভগুলি সহজ করে।

প্রথমটি বরং সহজ।

কল্পনা করুন আপনার কাছে এমন একটি এপিআই রয়েছে যা দেখে মনে হচ্ছে:

public interface SnickersCounter {
  /** 
   * Provides a proper count of how many snickers have been consumed in total.
   */
  public SnickersCount howManySnickersHaveBeenEaten();

  /**
    * returns the last snickers eaten.<br>
    * If no snickers have been eaten null is returned for contrived reasons.
    */
  public Snickers lastConsumedSnickers();
}

এবং এটির মতো আপনার ব্যবহারের একটি উত্তরাধিকার শ্রেণি ছিল (শূন্যস্থান পূরণ করুন):

Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
  throw new NoSuchSnickersException();
}
else {
  consumer.giveDiabetes(lastSnickers);
}

নিশ্চিত হওয়ার একটি স্বতন্ত্র উদাহরণ example তবে এখানে আমার সাথে সহ্য করুন।

জাভা 8 এখন চালু হয়েছে এবং আমরা আরোহণের জন্য কাঁপছি। সুতরাং আমরা যা করি তার মধ্যে একটি হ'ল আমরা আমাদের পুরানো ইন্টারফেসটি এমন কিছু দিয়ে প্রতিস্থাপন করতে চাই যা ptionচ্ছিক ফিরে আসে। কেন? কারণ অন্য কেউ ইতিমধ্যে করুণাময়ভাবে উল্লেখ করেছেন: কিছু শূন্য হতে পারে কি না তা এই অনুমানের কাজটি গ্রহণ করে যা ইতিমধ্যে অন্যরা এটি নির্দেশ করেছে। তবে এখন আমাদের সমস্যা আছে। কল্পনা করুন যে আমাদের রয়েছে (আমি নির্দোষ পদ্ধতিতে Alt + F7 চাপার সময় আমাকে ক্ষমা করুন), 46 টি জায়গায় যেখানে এই পদ্ধতিটি ভাল পরীক্ষিত উত্তরাধিকার কোডে বলা হয় যা অন্যথায় একটি দুর্দান্ত কাজ করে। এখন আপনাকে এই সমস্ত আপডেট করতে হবে।

এটিই যেখানে ইজপ্রেসেট জ্বলজ্বল করে।

কারণ এখন: স্নিকার্স লাস্ট সনিকারস = স্নিকারসনকাউন্টার.লাস্টকনস্মস্নস্নেকারস (); যদি (নাল == সর্বশেষ স্নিকার্স) {নতুন নুশচনসনিকার্সেক্সপশন () নিক্ষেপ করুন; } অন্য {ভোক্তা। ডায়াবেটিস (সর্বশেষ স্নিকার্স); }

হয়ে:

Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
  throw new NoSuchSnickersException();
}
else {
  consumer.giveDiabetes(lastSnickers.get());
}

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

লক্ষ্য করুন যে এর অর্থ হল যেভাবে আপনি এটি করেছিলেন তা মূলত ব্যয়বহুল লেখাগুলি না করেই উত্তরাধিকারের কোডটি মোকাবেলা করার একটি উপায়। সুতরাং নতুন কোড সম্পর্কে কি?

ভাল, আপনার ক্ষেত্রে যেখানে আপনি কেবল কিছু মুদ্রণ করতে চান, আপনি কেবল তা করতে চাইবেন:

। SnickersCounter.lastConsumedSnickers () ifPresent (System.out :: println);

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

  • আপনি এমন একটি পদ্ধতি কল করছেন যা শূন্য হতে পারে। সঠিক ধারণাটি হ'ল পদ্ধতিটি শূন্য হয়।
  • ল্যাম্বদা ফ্যানসিটিযুক্ত স্বাদযুক্ত নতুন পদ্ধতি ব্যবহারের পরিবর্তে আপনি এই alচ্ছিকটি মোকাবেলা করার জন্য উত্তরাধিকার বান্দাইড পদ্ধতি ব্যবহার করছেন।

আপনি যদি একটি সাধারণ নাল-সুরক্ষা চেক হিসাবে ptionচ্ছিক ব্যবহার করতে চান তবে আপনার যা করা উচিত তা কেবল এটি:

new Optional.ofNullable(employeeServive.getEmployee())
    .map(Employee::getId)
    .ifPresent(System.out::println);

অবশ্যই, এটির মতো দেখতে সুন্দর সংস্করণটি:

employeeService.getEmployee()
    .map(Employee::getId)
    .ifPresent(System.out::println);

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

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


1
এখানে সমস্যাটি হ'ল আপনি এটিকে শব্দ করার চেষ্টা করেছেন যে এই কার্যকরী সংস্করণগুলি পুরানো সংস্করণগুলির মতোই পঠনযোগ্য, এক ক্ষেত্রে এমনকি একটি উদাহরণও বলা হয়েছে "পুরোপুরি পরিষ্কার"। ব্যাপার সেটা না. এই উদাহরণটি স্পষ্ট ছিল, তবে পুরোপুরি তাই নয়, কারণ এতে আরও চিন্তাভাবনা প্রয়োজন। map(x).ifPresent(f)কেবল একই ধরণের স্বজ্ঞাত জ্ঞান if(o != null) f(x)দেয় না যা করে। ifসংস্করণ পুরোপুরি স্পষ্ট। এটি একটি জনপ্রিয় ব্যান্ড-ওয়াগনে ঝাঁপিয়ে পড়া লোকের আরেকটি ঘটনা, * সত্যিকারের অগ্রগতির ক্ষেত্রে নয়
হারুন

1
নোট করুন যে আমি বলছি না যে কার্যকরী প্রোগ্রামিং বা এর ব্যবহারে শূন্য সুবিধা রয়েছে Optional। আমি কেবলমাত্র এই নির্দিষ্ট ক্ষেত্রে alচ্ছিক ব্যবহারের কথা উল্লেখ করছিলাম এবং পাঠযোগ্যতার পক্ষে আরও অনেকগুলি লোকেরা যেহেতু একাধিক লোক এই ফর্ম্যাটটির মতো আচরণ করছে তার চেয়ে সমান বা বেশি পাঠযোগ্য if
হারুন

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

@ অ্যারন - স্পষ্টতা ptionচ্ছিক ধরণের বিন্দু নয়। আমি ব্যক্তিগতভাবে দেখতে পাচ্ছি যে তারা স্পষ্টতা হ্রাস করে না , এবং এমন কিছু কেস রয়েছে (যদিও এই ক্ষেত্রে নয়) যেখানে তারা এটি বৃদ্ধি করে তবে মূল উপকারটি হ'ল (যতক্ষণ না আপনি ব্যবহার এড়াতে পারবেন isPresentএবং getযতটা সম্ভব বাস্তবতাই সম্ভব) তারা নিরাপত্তা উন্নতি । ভুল কোডটি লেখা শক্ত যে এটি Optional<Whatever>কোনও অযোগ্য ব্যবহারের চেয়ে প্রকারের পরিবর্তে যদি মানটির অনুপস্থিতি যাচাই করতে ব্যর্থ হয় Whatever
জুলাইস

এমনকি যদি আপনি অবিলম্বে মান গ্রহণ করা, যতদিন না পর্যন্ত আপনি ব্যবহার করবেন না যেমনget , আপনি কি করতে হবে তা নির্বাচন করার যখন একটি অনুপস্থিত মান ঘটে বাধ্য করছেন যারা আপনি হয় ব্যবহার করেন orElse()(অথবা orElseGet()) একটি ডিফল্ট সরবরাহ, অথবা orElseThrow()নিক্ষেপ করার জন্য একটি মনোনীত ব্যতিক্রম যে সমস্যার প্রকৃতির ডকুমেন্ট , যা জেনেরিক এনপিইর চেয়ে ভাল যা আপনি স্ট্যাক ট্রেসটিতে খনন না করা পর্যন্ত অর্থহীন।
জুলাইস

0

স্টাইল ২-এ আমি কোনও সুবিধা দেখছি না, আপনার এখনও বুঝতে হবে যে আপনার নাল চেকের প্রয়োজন এবং এটি এখন আরও বড়, এইভাবে কম পাঠযোগ্য।

আরও ভাল স্টাইলটি হ'ল, যদি কর্মচারী সার্ভে.জেট এমপ্লয়ই () returnচ্ছিক ফিরে আসে এবং তারপরে কোডটি হয়ে যায়:

Optional<Employee> employeeOptional = employeeServive.getEmployee();
if(employeeOptional.isPresent()){
    Employee employee= employeeOptional.get();
    System.out.println(employee.getId());
}

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


12
আপনি যে মুহুর্তটি ব্যবহার করবেন সেই মুহূর্তে ptionচ্ছিক একটি অর্থহীন জটিলতায় পরিণত হয় isPresent()। আমরা useচ্ছিক ব্যবহার করি যাতে আমাদের পরীক্ষা করতে হবে না।
candied_orange

2
অন্যরা যেমন বলেছেন, ব্যবহার করবেন না isPresent()। এটি বিকল্পগুলির পক্ষে ভুল পদ্ধতি। ব্যবহার করুন mapঅথবা flatMapপরিবর্তে।
আন্দ্রেস এফ

1
@ ক্যান্ডিওড অ্যারেঞ্জ এবং তবুও শীর্ষ-ভোট প্রাপ্ত উত্তর (ব্যবহারের জন্য বলা ifPresent) পরীক্ষা করার আরও একটি উপায়।
ইমিগ্রিস

1
@ ক্যান্ডিওড অ্যারেঞ্জ ifPresent(x)কেবলমাত্র একটি পরীক্ষার মতো if(present) {x}। ফেরতের মান অপ্রাসঙ্গিক।
imivis

1
@ ক্যান্ডিড ওরেঞ্জ তবুও, আপনি মূলত বলেছিলেন "সুতরাং আমাদের পরীক্ষা করার দরকার নেই।" আপনি যখন সত্যই এখনও পরীক্ষা করছেন ... আপনি যা করছেন তখন আপনি "সুতরাং আমাদের পরীক্ষা করতে হবে না" বলতে পারবেন না।
হারুন

0

আমি মনে করি সবচেয়ে বড় সুবিধা হ'ল যদি আপনার পদ্ধতির স্বাক্ষর কোনও ফিরিয়ে দেয় তবে Employeeআপনি নালার জন্য যাচাই করবেন না । আপনি যে স্বাক্ষর দ্বারা জানেন যে এটি কোনও কর্মী ফিরিয়ে দেওয়ার গ্যারান্টিযুক্ত। আপনার একটি ব্যর্থতা কেস পরিচালনা করার দরকার নেই। একটি alচ্ছিক সঙ্গে আপনি জানেন যে।

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

তবে এটি কাজ করার জন্য আপনাকে এই প্যাটার্নটি ধারাবাহিকভাবে প্রয়োগ করতে হবে।


1
এটি অর্জনের সহজ উপায় হ'ল স্থির বিশ্লেষণ ব্যবহার করে @Nullableএবং @ReturnValuesAreNonnullByDefaultএকত্রে।
মার্টিনাস

@ Maaartinus ডেকরেটার টীকাগুলিতে স্থির বিশ্লেষণ এবং ডকুমেন্টেশনের আকারে অতিরিক্ত টুলিং যুক্ত করা কি সহজ সময় টাইপ API সমর্থন সংকলন করে?
18'18

অতিরিক্ত টুলিং যুক্ত করা সহজতর ধরণের সহজ, কারণ এতে কোনও কোড পরিবর্তন করার প্রয়োজন নেই। তদুপরি, এটি অন্য বাগগুলিও ক্যাচ করার সাথে সাথে আপনি রাখতে চান way +++ আমি যোগ করার সময় একটি তুচ্ছ স্ক্রিপ্ট লিখেছিলেন package-info.javaসঙ্গে @ReturnValuesAreNonnullByDefaultআমার সমস্ত প্যাকেজ, তাই আমি যা করতে হবে যোগ হয় @Nullableযেখানে আপনি এ স্যুইচ করতে হবে Optional। এর অর্থ কম অক্ষর, কোনও অতিরিক্ত আবর্জনা এবং কোনও রানটাইম-ওভারহেড। পদ্ধতির উপর ঘোরাঘুরি করার সময় আমাকে ডকুমেন্টেশনগুলি সন্ধান করতে হবে না। স্থিতিশীল বিশ্লেষণ সরঞ্জাম ভুলগুলি এবং পরে শূণ্যতা পরিবর্তনগুলি ক্যাচ করে।
মার্টিনাস

আমার সবচেয়ে বড় উদ্বেগ Optionalএটি হ'ল এটি শূন্যতার সাথে আচরণ করার একটি বিকল্প উপায় যুক্ত করে। এটি প্রথম থেকেই জাভাতে থাকলে এটি ভাল হতে পারে তবে এখন এটি কেবল ব্যথা। কোটলিন যাওয়ার পথে আইএমএইচও হবে আরও ভাল। +++ নোট এটি List<@Nullable String>এখনও স্ট্রিংগুলির একটি তালিকা, যদিও List<Optional<String>>নেই।
maarartinus

0

আমার উত্তর: ঠিক না। এটি আসলে কোনও উন্নতি কিনা তা নিয়ে কমপক্ষে দু'বার ভাবেন।

মত প্রকাশ (অন্য উত্তর থেকে নেওয়া) পছন্দ

Optional.of(employeeService)                 // definitely have the service
        .map(EmployeeService::getEmployee)   // getEmployee() might return null
        .map(Employee::getId)                // get ID from employee if there is one
        .ifPresent(System.out::println);     // and if there is an ID, print it

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

এটি পুরানো শৈলীর চেয়ে ভাল দেখাচ্ছে

Employee employee = employeeService.getEmployee();
if (employee != null) {
    ID id = employee.getId();
    if (id != null) {
        System.out.println(id);
    }
}

যা এটিকে স্পষ্ট করে তোলে যে এখানে elseধারা থাকতে পারে ।

কার্যকরী শৈলী

  • সম্পূর্ণ ভিন্ন দেখায় (এবং এটি অব্যবহৃত লোকদের জন্য অপঠনযোগ্য)
  • ডিবাগ করার জন্য একটি ব্যথা
  • "অনুপস্থিত" কেস পরিচালনা করার জন্য সহজে বাড়ানো যায় না ( orElseসর্বদা যথেষ্ট নয়)
  • "অনুপস্থিত" কেস উপেক্ষা করার জন্য বিভ্রান্ত করে

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


একটি বড় জাভা অনুরাগী হওয়ার সময়, আমার অবশ্যই বলতে হবে যে কার্যকরী শৈলীটি একটি গরীব জাভা মানুষের বিবৃতিটির বিকল্প

employeeService
.getEmployee()
?.getId()
?.apply(id => System.out.println(id));

অন্যান্য ভাষা থেকে সুপরিচিত। আমরা কি এই বিবৃতিতে সম্মত হই?

  • (সত্যই) কার্যকরী হয় না?
  • পুরাতন স্টাইলের কোডটির সাথে কি খুব সাদৃশ্য?
  • কার্যকরী শৈলী চেয়ে অনেক বেশি পঠনযোগ্য?
  • ডিবাগার বান্ধব?

আপনি সি # 'গুলি বর্ণনা হবে বলে মনে হচ্ছে বাস্তবায়ন যেমন সম্পূর্ণভাবে জাভার বিভিন্ন একটি ভাষা বৈশিষ্ট্য সঙ্গে এই ধারণার বাস্তবায়ন মূল গ্রন্থাগার বর্গ সঙ্গে। তারা আমার কাছে একই দেখাচ্ছে
ক্যালথ

@ ক্যালথ কোনও উপায় নেই আমরা "নাল-সেফ মূল্যায়ন সহজ করার ধারণা" সম্পর্কে বলতে পারি, তবে আমি এটিকে "ধারণা" বলব না। আমরা বলতে পারি যে একটি মূল গ্রন্থাগার ক্লাস ব্যবহার করে জাভা একই জিনিস প্রয়োগ করে, তবে এটি কেবল গোলমাল। employeeService.getEmployee().getId().apply(id => System.out.println(id));নিরাপদ নেভিগেশন অপারেটরটি একবার ব্যবহার করে এবং একবার ব্যবহার করে একবার দিয়ে শুরু করুন এবং এটিকে নাল-নিরাপদ করুন Optional। অবশ্যই, আমরা এটিকে একটি "বাস্তবায়ন বিশদ" বলতে পারি, তবে বাস্তবায়নের বিষয়টি গুরুত্বপূর্ণ। লামডাস কোড সহজ ও সুন্দর করে তোলে এমন কিছু ক্ষেত্রে রয়েছে তবে এখানে এটি কেবল একটি কুৎসিত আপত্তি।
মার্টিনাস

লাইব্রেরী শ্রেণী: Optional.of(employeeService).map(EmployeeService::getEmployee).map(Employee::getId).ifPresent(System.out::println);ভাষা বৈশিষ্ট্য: employeeService.getEmployee()?.getId()?.apply(id => System.out.println(id));। দুটি বাক্য গঠন, তবে এগুলি আমার সাথে দেখতে খুব মিল রয়েছে । এবং "ধারণা" হয় Optionalওরফে NullableওরফেMaybe
Caleth

আপনি বুঝতে পারছেন না কেন আপনি এর মধ্যে একটি "কুৎসিত আপত্তি" এবং অন্যটি ভাল think আমি তোমাকে বুঝতে চিন্তা পারে উভয় "অরুপ অপব্যবহার" বা উভয় ভাল।
কালেথ

@ ক্যালথ এক পার্থক্য হ'ল দুটি প্রশ্ন চিহ্ন যুক্ত করার পরিবর্তে আপনাকে এগুলি আবার লিখতে হবে। সমস্যাটি নয় যে ভাষা বৈশিষ্ট্য এবং লাইব্রেরি ক্লাস কোডগুলি অনেক বেশি আলাদা। ঠিক আছে. সমস্যাটি হ'ল মূল কোড এবং লাইব্রেরি ক্লাস কোডগুলি অনেক বেশি আলাদা হয়। একই ধারণা, বিভিন্ন কোড। ওটা খুব খারাপ. +++যেটি আপত্তিজনক হয় তা হ'ল নমনীয়তা পরিচালনা করার জন্য লামদাস। লামদাস ঠিক আছে, তবে Optionalনেই। কোললিনির মতো নুলিয়াযোগ্যতার জন্য একটি উপযুক্ত ভাষা সমর্থন প্রয়োজন। আরেকটি সমস্যা: List<Optional<String>>এর সাথে সম্পর্কিত নয় List<String>, আমাদের সেগুলি সম্পর্কিত হওয়া দরকার।
মার্টিনাস

0

Ptionচ্ছিক একটি ধারণা (উচ্চতর আদেশের ধরণ) যা ক্রিয়ামূলক প্রোগ্রামিং থেকে আসে। এটি ব্যবহার করা নেস্টেড নাল চেকিংয়ের সাথে দূরে থাকে এবং আপনাকে ডুমের পিরামিড থেকে বাঁচায়।

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