সংক্ষেপে, পুনরায় ব্যবহারযোগ্যতার জন্য আপনার সফ্টওয়্যারটিকে ইঞ্জিনিয়ার করবেন না কারণ আপনার ফাংশনগুলি পুনরায় ব্যবহার করা যেতে পারে যদি কোনও শেষ ব্যবহারকারী যত্ন করে না। পরিবর্তে, ডিজাইন বোধগম্যতার জন্য ইঞ্জিনিয়ার - আমার কোড অন্য কারও পক্ষে বা আমার ভবিষ্যতের ভুলে যাওয়া স্ব বোঝার পক্ষে সহজ? - এবং নকশা নমনীয়তা- যখন আমাকে অনিবার্যভাবে বাগগুলি ঠিক করতে, বৈশিষ্ট্যগুলি যুক্ত করতে বা অন্যথায় কার্যকারিতা সংশোধন করতে হবে, তখন আমার কোড পরিবর্তনগুলি কতটা প্রতিহত করবে? আপনার গ্রাহক কেবলমাত্র তার যত্ন নেবেন তা হ'ল তিনি যখন কোনও বাগ রিপোর্ট করেন বা কোনও পরিবর্তন জিজ্ঞাসা করেন তখন আপনি কত দ্রুত প্রতিক্রিয়া জানাতে পারেন। আপনার নকশা সম্পর্কে এই প্রশ্নগুলি ঘটনাক্রমে পুনরায় ব্যবহারযোগ্য কোডের দিকে ঝোঁক দেয় তবে এই পদ্ধতির সাহায্যে আপনি সেই কোডটির জীবনকালে যে সত্যিকারের সমস্যাগুলির মুখোমুখি হবেন তা এড়ানোর দিকে মনোনিবেশ রাখে যাতে আপনি উচ্চতর, অবৈধের অনুসরণ না করে শেষ ব্যবহারকারীকে আরও ভালভাবে সেবা করতে পারেন ঘাড়-দাড়ি খুশি করার জন্য "ইঞ্জিনিয়ারিং" আদর্শ।
আপনি যে উদাহরণটি দিয়েছেন তার মতো সাধারণ কোনও কিছুর জন্য আপনার প্রাথমিক বাস্তবায়ন ঠিক আছে কারণ এটি কত ছোট, তবে আপনি যদি খুব বেশি কার্যকরী নমনীয়তা (নকশার নমনীয়তার বিপরীতে) জ্যাম করার চেষ্টা করেন তবে এই সরল নকশাটি বোঝা এবং ভঙ্গুর হয়ে উঠবে into একটি পদ্ধতি বোধগম্যতা এবং নমনীয়তার জন্য জটিল সিস্টেমগুলি ডিজাইনের বিষয়ে আমার পছন্দের পদ্ধতির নীচে আমার ব্যাখ্যা রয়েছে যা আমি আশা করি যে তাদের দ্বারা আমি কী বোঝাতে চাইছি তা প্রদর্শন করবে। আমি এই কৌশলটি এমন কোনও কিছুর জন্য নিয়োগ করব না যা একক পদ্ধতিতে 20 টিরও কম লাইনে লেখা যেতে পারে কারণ এত ছোট কিছু ইতিমধ্যে বোধগম্যতা এবং নমনীয়তার জন্য আমার মানদণ্ডকে মেটায়।
পদার্থ, পদ্ধতি নয়
আপনার সফ্টওয়্যারটি যে জিনিসগুলি করা উচিত তা সম্পাদন করার জন্য আপনি কল করার প্রচলিত রুটিনগুলির সাথে পুরাতন-স্কুল মডিউলগুলির মতো ক্লাস ব্যবহার করার পরিবর্তে, ডোমেনকে এমন বস্তু হিসাবে মডেলিংয়ের বিষয়টি বিবেচনা করুন যা কার্য সম্পাদন করার জন্য ইন্টারেক্ট করে এবং সহযোগিতা করে। একটি অবজেক্ট ওরিয়েন্টেড দৃষ্টান্ত পদ্ধতি মূলত বস্তুর মধ্যে সংকেত হতে যাতে তৈরি করা হয়েছিল Object1
বলতে পারতাম Object2
তার জিনিস, যাই হোক না কেন যে করতে হবে, এবং সম্ভবত একটি ফিরতি সংকেত। এর কারণ হ'ল অবজেক্ট-ওরিয়েন্টড দৃষ্টান্তটি ইমপ্রেটিভ দৃষ্টান্তের একই পুরানো ফাংশন এবং পদ্ধতিগুলি বিন্যস্ত করার অভিনব উপায়ের চেয়ে আপনার ডোমেন অবজেক্টগুলি এবং তাদের মিথস্ক্রিয়াগুলির মডেলিং সম্পর্কে অন্তর্নিহিত। ক্ষেত্রেvoid destroyBaghdad
উদাহরণস্বরূপ, বাগদাদ বা অন্য যে কোনও কিছুর (যা দ্রুত জটিল, বোঝা শক্ত, এবং ভঙ্গুর বিকাশ ঘটতে পারে) পরিচালনা করতে প্রসঙ্গে কম জেনেরিক পদ্ধতি লেখার চেষ্টা করার পরিবর্তে, ধ্বংস হওয়া প্রতিটি জিনিসই কীভাবে বোঝার জন্য দায়বদ্ধ হতে হবে নিজেকে ধ্বংস করতে। উদাহরণস্বরূপ, আপনার একটি ইন্টারফেস রয়েছে যা ধ্বংস হতে পারে এমন আচরণগুলির বর্ণনা দেয়:
interface Destroyable {
void destroy();
}
তারপরে আপনার একটি শহর রয়েছে যা এই ইন্টারফেসটি প্রয়োগ করে:
class City implements Destroyable {
@Override
public void destroy() {
...code that destroys the city
}
}
কোনও উদাহরণ যা ধ্বংসের জন্য ডেকেছে City
তা কখনই কীভাবে ঘটে সেদিকে খেয়াল রাখে না, সুতরাং সেই কোডটির বাইরে কোথাও অস্তিত্ব থাকার কোনও কারণ নেই City::destroy
এবং প্রকৃতপক্ষে, City
নিজের বাহিরের অভ্যন্তরীণ কাজগুলির অন্তরঙ্গ জ্ঞানটি সংঘাতযুক্ত মিলন হবে যা হ্রাস পাবে আপত্তিজনক যেহেতু আপনাকে বাহ্যিক উপাদানগুলি বিবেচনা করতে হবে আপনার কখনই এর আচরণটি পরিবর্তন করতে হবে City
। এটি এনক্যাপসুলেশনের পিছনে আসল উদ্দেশ্য। এটিকে ভাবুন যেমন প্রতিটি বস্তুর নিজস্ব এপিআই থাকে যা আপনাকে এটির সাথে যা কিছু করার প্রয়োজন তা করতে সক্ষম করে তোলে যাতে আপনি এটি আপনার অনুরোধগুলি পূরণ করার বিষয়ে উদ্বিগ্ন হতে পারেন।
প্রতিনিধি, "নিয়ন্ত্রণ" নয়
এখন, আপনার বাস্তবায়নকারী শ্রেণি কিনা City
বা Baghdad
শহরটিকে ধ্বংস করার প্রক্রিয়াটি কী জেনারিক হতে পারে তার উপর নির্ভর করে। সমস্ত সম্ভাবনার ক্ষেত্রে, একটি City
ছোট ছোট টুকরো দ্বারা তৈরি করা হবে যা শহরের সম্পূর্ণ ধ্বংস সাধনের জন্য স্বতন্ত্রভাবে ধ্বংস করা প্রয়োজন, সুতরাং সেই ক্ষেত্রে, সেই টুকরাগুলির প্রত্যেকটি বাস্তবায়িত হবে Destroyable
, এবং তাদের প্রত্যেককে City
ধ্বংস করার নির্দেশ দেওয়া হবে তারা নিজেরাই ঠিক একইভাবে বাইরে থেকে এসেছিল City
যাতে সে নিজেকে ধ্বংস করতে পারে।
interface Part extends Destroyable {
...part-specific methods
}
class Building implements Part {
...part-specific methods
@Override
public void destroy() {
...code to destroy a building
}
}
class Street implements Part {
...part-specific methods
@Override
public void destroy() {
...code to destroy a building
}
}
class City implements Destroyable {
public List<Part> parts() {...}
@Override
public void destroy() {
parts().forEach(Destroyable::destroy);
}
}
আপনি যদি সত্যিই পাগল হয়ে যেতে চান এবং এমন কোনও ধারণাটি প্রয়োগ করতে চান যা কোনও কোনও Bomb
জায়গায় ফেলে দেওয়া হয় এবং একটি নির্দিষ্ট ব্যাসার্ধের মধ্যে সমস্ত কিছুকে ধ্বংস করে দেয় তবে এটি দেখতে এরকম কিছু হতে পারে:
class Bomb {
private final Integer radius;
public Bomb(final Integer radius) {
this.radius = radius;
}
public void drop(final Grid grid, final Coordinate target) {
new ObjectsByRadius(
grid,
target,
this.radius
).forEach(Destroyable::destroy);
}
}
ObjectsByRadius
Bomb
ইনপুটগুলি থেকে গণনার জন্য অবজেক্টের একটি সেট উপস্থাপন করে কারণ Bomb
বস্তুগুলির সাথে কাজ করতে পারে সেভাবে সেই গণনাটি কীভাবে করা যায় তা কতক্ষণ যত্ন করে না। এটি ঘটনাক্রমে পুনরায় ব্যবহারযোগ্য, তবে মূল লক্ষ্য হ'ল Bomb
বস্তুগুলি ফেলে দেওয়ার এবং ধ্বংস করার প্রক্রিয়াগুলি থেকে গণনাটি বিচ্ছিন্ন করা যাতে আপনি প্রতিটি টুকরো বুঝতে পারেন এবং সেগুলি কীভাবে একসাথে ফিট হয়ে যায় এবং সম্পূর্ণ অ্যালগরিদমকে পুনরায় আকার না দিয়ে পৃথক টুকরার আচরণ পরিবর্তন করতে পারে you ।
মিথস্ক্রিয়া, অ্যালগরিদম নয়
একটি জটিল অ্যালগরিদমের জন্য সঠিক সংখ্যক পরামিতি অনুমান করার চেষ্টা করার পরিবর্তে, প্রক্রিয়াটিকে আন্তঃসংযোগমূলক সামগ্রীর একটি সেট হিসাবে, প্রতিটি অত্যন্ত সংকীর্ণ ভূমিকা সহ একটি মডেল তৈরি করা আরও বোধগম্য করে তোলে যেহেতু এটি আপনাকে আপনার জটিলতার মডেল করার ক্ষমতা দেয় এই ভাল-সংজ্ঞায়িত, উপলব্ধি করা সহজ, এবং প্রায় অপরিবর্তনীয় অবজেক্টের মধ্যে মিথস্ক্রিয়া মাধ্যমে প্রক্রিয়া। সঠিকভাবে সম্পন্ন করার পরে এটি কিছু জটিল পরিবর্তনকে এমনকি একটি ইন্টারফেস বা দুটি প্রয়োগ করে এবং কোন main()
পদ্ধতিতে আপনার পদ্ধতিতে ইনস্ট্যান্ট হয় তা পুনরায় কাজ করার মতো তুচ্ছ হিসাবে তোলে makes
আমি আপনাকে আপনার মূল উদাহরণটিতে কিছু উপহার দেব, তবে "মুদ্রণ ... দিবালোক সঞ্চয়" এর অর্থ কী তা আমি সত্যই বুঝতে পারি না। সমস্যাটির এই বিভাগ সম্পর্কে আমি যা বলতে পারি তা হ'ল যে সময় আপনি কোনও গণনা করছেন, ফলাফলটি বেশ কয়েকটি উপায়ে ফর্ম্যাট করা যেতে পারে, আমার এটি ভেঙে দেওয়ার জন্য আমার পছন্দের উপায়টি হ'ল:
interface Result {
String print();
}
class Caclulation {
private final Parameter paramater1;
private final Parameter parameter2;
public Calculation(final Parameter parameter1, final Parameter parameter2) {
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
public Result calculate() {
...calculate the result
}
}
class FormattedResult {
private final Result result;
public FormattedResult(final Result result) {
this.result = result;
}
@Override
public String print() {
...interact with this.result to format it and return the formatted String
}
}
যেহেতু আপনার উদাহরণটি জাভা লাইব্রেরির ক্লাসগুলি ব্যবহার করে যা এই নকশাটিকে সমর্থন করে না, আপনি কেবল ZonedDateTime
সরাসরি এর API ব্যবহার করতে পারেন । এখানে ধারণাটি হ'ল প্রতিটি গণনা তার নিজস্ব বস্তুর মধ্যে আবদ্ধ হয় ap এটি কতবার চালানো উচিত বা ফলাফলটি কীভাবে ফর্ম্যাট করা উচিত সে সম্পর্কে কোনও অনুমান করে না। এটি গণনার সহজতম রূপটি সম্পাদনের সাথে একচেটিয়াভাবে সম্পর্কিত। এটি উভয়ই বোঝা সহজ এবং পরিবর্তনের জন্য নমনীয় করে তোলে। তেমনি, Result
গণনাটির ফলাফলকে encapsulate করার সাথে একচেটিয়াভাবে উদ্বেগ প্রকাশিত হয় এবং আমরা যে বিধিগুলি সংজ্ঞায়িত করি তার অনুসারে এটি ফর্ম্যাট করার FormattedResult
জন্য একচেটিয়াভাবে সম্পর্কিত is Result
এইভাবে,আমরা আমাদের প্রতিটি পদ্ধতির জন্য নিখুঁত সংখ্যক যুক্তি খুঁজে পেতে পারি যেহেতু তাদের প্রত্যেকের একটি সুস্পষ্ট নির্ধারিত টাস্ক রয়েছে । ইন্টারফেসগুলি পরিবর্তিত হয় না এমনভাবে দীর্ঘ অগ্রসর হওয়া সংশোধন করাও সহজ (আপনি যদি আপনার বস্তুর দায়বদ্ধতা যথাযথভাবে কমিয়ে দেন তবে তারা এগুলি করার মতো সম্ভাবনা নয়)। আমাদেরmain()
পদ্ধতিটি দেখতে দেখতে এটির মতো হতে পারে:
class App {
public static void main(String[] args) {
final List<Set<Paramater>> parameters = ...instantiated from args
parameters.forEach(set -> {
System.out.println(
new FormattedResult(
new Calculation(
set.get(0),
set.get(1)
).calculate()
).print()
);
});
}
}
প্রকৃতপক্ষে, অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংটি বিশেষভাবে ইমপ্লেরিটিভ দৃষ্টান্তের জটিলতা / নমনীয়তার সমস্যার সমাধান হিসাবে আবিষ্কার করা হয়েছিল কারণ সর্বোত্তম উপায় কীভাবে করা যায় তার সঠিক কোনও ভাল উত্তর নেই (যে প্রত্যেকেই একমত হতে পারে বা স্বাধীনভাবে উপস্থিত হতে পারে) প্রতিমাটির মধ্যে আবশ্যকীয় কার্যাদি এবং পদ্ধতিগুলি নির্দিষ্ট করুন।