Java में Functional बनाम Object-Oriented: आधुनिक डेवलपर को क्या चुनना चाहिए?
\n\nJava की दुनिया में दो दिग्गजों के बीच जंग छिड़ी हुई है। एक तरफ क्लासिक Object-Oriented Programming (OOP) है, जिसने डेवलपर्स की पूरी पीढ़ी को तैयार किया। दूसरी तरफ तेजी से उभरता Functional Approach है, जो Java 8 के साथ इस इकोसिस्टम में आया और आज भी बहस जारी है: "क्या हमें इसकी ज़रूरत है?"
\n\nअगर आप Java में कोड लिखते हैं, तो आप रोज़ इस चुनाव का सामना करते हैं। क्या एक साधारण फिल्टरेशन के लिए पूरी क्लास और मेथड बनाना चाहिए? या फिर लैम्ब्डा की चेन लगाकर काम खत्म करना चाहिए? इस आर्टिकल में हम किसी का पक्ष नहीं लेंगे। हम दोनों तरीकों को रियल उदाहरणों से समझेंगे, उनकी तुलना करेंगे और आपको यह तय करने में मदद करेंगे कि कब कौन सा टूल इस्तेमाल करना है।
\n\nएक छोटी सी पृष्ठभूमि: हम यहाँ तक कैसे पहुंचे
\n\nJava को शुरू में पूरी तरह से Object-Oriented भाषा के रूप में डिज़ाइन किया गया था। सब कुछ एक ऑब्जेक्ट है। यहाँ तक कि एक स्ट्रिंग भी String क्लास का ऑब्जेक्ट है। क्लासेस, इनहेरिटेंस, पॉलीमॉर्फिज़्म - यही धर्म था। लेकिन समय बदला और डेवलपर्स ने महसूस किया: OOP रियल वर्ल्ड (कार, कर्मचारी, ऑर्डर) को मॉडल करने में तो बेहतरीन है, लेकिन डेटा स्ट्रीम को प्रोसेस करने में बुरी तरह फेल हो जाता है।
तब मंच पर आए लैम्ब्डा एक्सप्रेशन और Stream API। Java कोई फंक्शनल लैंग्वेज (जैसे Haskell या Scala) नहीं बनी, लेकिन इसने उस पैराडाइम से सबसे अच्छी चीजें उधार लीं। अब हमारे पास चुनाव है: क्लास के मेथड के अंदर for लूप लिखें या filter().map().collect() का उपयोग करें।
Object-Oriented Approach: क्लासिक अंदाज़
\n\nJava में OOP चार स्तंभों पर टिका है: एनकैप्सुलेशन, इनहेरिटेंस, पॉलीमॉर्फिज़्म और एब्स्ट्रैक्शन। जब आप बिज़नेस लॉजिक पर काम करते हैं, जहाँ एंटिटीज़ (यूज़र, ऑर्डर, प्रोडक्ट) होती हैं, तो OOP स्वाभाविक विकल्प है।
\n\nयहाँ एक क्लासिक समस्या का उदाहरण है: 2024 में किए गए किसी ग्राहक के सभी ऑर्डरों की कुल राशि निकालना।
\n\nObject-Oriented समाधान:
\n\nimport java.util.List;\n\npublic class OrderService {\n\n public double calculateTotal2024(List<Order> orders) {\n double total = 0.0;\n for (Order order : orders) {\n if (order.getYear() == 2024) {\n total += order.getAmount();\n }\n }\n return total;\n }\n}\n\nclass Order {\n private int year;\n private double amount;\n\n public Order(int year, double amount) {\n this.year = year;\n this.amount = amount;\n }\n\n public int getYear() { return year; }\n public double getAmount() { return amount; }\n}\n\nसब कुछ साफ़, पढ़ने में आसान, डीबग करना आसान। कोई भी जूनियर समझ जाएगा कि यहाँ क्या हो रहा है। लेकिन एक बात है: कोड इम्पेरेटिव है। हम बता रहे हैं कैसे करना है (एक वेरिएबल बनाओ, लिस्ट पर चलो, कंडीशन चेक करो, जोड़ो)।
\n\nFunctional Approach: डिक्लेरेटिव तरीका
\n\nJava में Functional Programming इस बारे में है कि हम क्या पाना चाहते हैं, न कि कैसे। हम हायर-ऑर्डर फंक्शन, इम्यूटेबिलिटी और साइड इफेक्ट्स की अनुपस्थिति का उपयोग करते हैं।
\n\nवही काम, लेकिन फंक्शनल स्टाइल में:
\n\nFunctional समाधान:
\n\nimport java.util.List;\n\npublic class OrderServiceFunctional {\n\n public double calculateTotal2024(List<Order> orders) {\n return orders.stream()\n .filter(order -> order.getYear() == 2024)\n .mapToDouble(Order::getAmount)\n .sum();\n }\n}\n\nसिर्फ तीन लाइनें। कोई म्यूटेबल वेरिएबल नहीं, कोई लूप नहीं। हम बस कहते हैं: "स्ट्रीम लो, साल के हिसाब से फ़िल्टर करो, रकम निकालो, जोड़ दो।" यह डिक्लेरेटिव स्टाइल है।
\n\nतुलना: कहाँ क्या बेहतर है?
\n\nआइए समझते हैं कि किन परिस्थितियों में कौन सा तरीका बेहतर काम करता है।
\n\n1. पढ़ने में आसानी और संक्षिप्तता
\nविजेता: Functional