मुझे कैसे पता चलेगा कि मेरे तरीके कितने पुन: प्रयोज्य होने चाहिए? [बन्द है]


133

मैं घर पर अपना खुद का व्यवसाय करने का मन बना रहा हूं और मेरी पत्नी मेरे पास आती है और कहती है

हनी .. क्या आप कंसोल में 2018 के लिए दुनिया भर के सभी डे लाइट सेविंग प्रिंट कर सकते हैं? मुझे कुछ जांचने की जरूरत है।

और मैं सुपर खुश हूं क्योंकि मैं अपने जावा अनुभव के साथ पूरी जिंदगी इंतजार कर रहा था।

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(2018, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (2018 == now.getYear()) {
                    int hour = now.getHour();
                    now = now.plusHours(1);
                    if (now.getHour() == hour) {
                        System.out.println(now);
                    }
                }
            }
        );
    }
}

लेकिन फिर वह कहती है कि वह सिर्फ मेरा परीक्षण कर रही थी कि क्या मैं एक नैतिक रूप से प्रशिक्षित सॉफ्टवेयर इंजीनियर थी, और मुझे बताती है कि ऐसा लगता है जैसे मैं ( यहाँ से लिया गया ) नहीं हूँ ।

यह ध्यान दिया जाना चाहिए कि कोई भी नैतिक रूप से प्रशिक्षित सॉफ्टवेयर इंजीनियर कभी भी एक विनाशकबगद प्रक्रिया लिखने के लिए सहमति नहीं देगा। इसके बजाय बुनियादी पेशेवर नैतिकता को उसे एक विध्वंस प्रक्रिया लिखने की आवश्यकता होगी, जिसमें बगदाद को एक पैरामीटर के रूप में दिया जा सकता है।

और मैं जैसा हूँ, ठीक है, ठीक है, आप मुझे मिल गए .. किसी भी वर्ष को पसंद करें, यहाँ आप जाएँ:

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings(int year) {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(year, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (year == now.getYear()) {
                    // rest is same..

लेकिन मुझे कैसे पता चलेगा कि कितना (और क्या) पैरामीटर बनाना है? आखिर, वह कह सकती है ..

  • वह एक कस्टम स्ट्रिंग फॉर्मेटर पास करना चाहती है, शायद उसे वह प्रारूप पसंद नहीं है जिसे मैं पहले से ही प्रिंट कर रही हूं: 2018-10-28T02:00+01:00[Arctic/Longyearbyen]

void dayLightSavings(int year, DateTimeFormatter dtf)

  • वह केवल कुछ महीनों की अवधि में रुचि रखती है

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd)

  • वह कुछ घंटों की अवधि में रुचि रखती है

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd, int hourStart, int hourend)

यदि आप एक ठोस प्रश्न की तलाश में हैं:

अगर destroyCity(City city)तुलना में बेहतर है destroyBaghdad(), है takeActionOnCity(Action action, City city)भी बेहतर? क्यों नहीं?

आखिरकार, मैं पहले इसे Action.DESTROYतब तक कह सकता हूं Action.REBUILD, है न?

लेकिन शहरों पर कार्रवाई करना मेरे लिए पर्याप्त नहीं है, कैसे takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea)? आखिरकार, मैं फोन नहीं करना चाहता:

takeActionOnCity(Action.DESTORY, City.BAGHDAD);

फिर

takeActionOnCity(Action.DESTORY, City.ERBIL);

और जब मैं ऐसा कर सकता हूं, तो:

takeActionOnGeographicArea(Action.DESTORY, Country.IRAQ);

पीएस मैंने केवल मेरे प्रश्न का उल्लेख किया है, मेरे पास दुनिया में किसी भी देश, धर्म, जाति या किसी के खिलाफ कुछ भी नहीं है। मैं सिर्फ एक बिंदु बनाने की कोशिश कर रहा हूं।



71
यहां आप जो बिंदु बना रहे हैं, वह वह है जिसे मैंने कई बार व्यक्त करने की कोशिश की है: सामान्यता महंगी है, और इसलिए इसे विशिष्ट, स्पष्ट लाभों द्वारा उचित ठहराया जाना चाहिए । लेकिन यह उससे कहीं अधिक गहरा है; प्रोग्रामिंग भाषाएं उनके डिजाइनरों द्वारा दूसरों की तुलना में कुछ प्रकार की व्यापकता को आसान बनाने के लिए बनाई गई हैं, और जो डेवलपर्स के रूप में हमारी पसंद को प्रभावित करती हैं। यह है आसान एक मूल्य के द्वारा एक विधि parameterize करने के लिए, और जब कि आप अपने पिटारे में है सबसे आसान उपकरण है, प्रलोभन है कि क्या यह उपयोगकर्ता के लिए समझ में आता है की परवाह किए बिना इसका इस्तेमाल करने की है।
एरिक लिपर्ट

30
पुन: उपयोग कुछ ऐसा नहीं है जिसे आप अपने लिए चाहते हैं। हम पुन: उपयोग को प्राथमिकता देते हैं क्योंकि हमारे पास यह विश्वास है कि कोड कलाकृतियों का निर्माण करना महंगा है और इसलिए उन परिदृश्यों में उस लागत को बढ़ाने के लिए यथासंभव अधिक से अधिक परिदृश्यों में उपयोग करने योग्य होना चाहिए। यह विश्वास अक्सर टिप्पणियों द्वारा उचित नहीं है, और पुन: प्रयोज्य के लिए डिजाइन करने की सलाह इसलिए अक्सर गलत होती हैएप्लिकेशन की कुल लागत को कम करने के लिए अपना कोड डिज़ाइन करें ।
एरिक लिपर्ट

7
आपकी पत्नी आपसे झूठ बोलकर अपना समय बर्बाद करने के लिए अनैतिक है। उसने एक जवाब मांगा, और एक सुझाव दिया माध्यम दिया; उस अनुबंध के द्वारा, आप कैसे प्राप्त करते हैं कि आउटपुट केवल आपके और आपके बीच है। इसके अलावा, destroyCity(target)जिस तरह से अधिक अनैतिक है destroyBagdad()! किस तरह का राक्षस किसी शहर को मिटा देने का कार्यक्रम लिखता है, दुनिया के किसी भी शहर को अकेला छोड़ दो? क्या होगा अगर सिस्टम समझौता किया गया था ?! इसके अलावा, समय / संसाधन प्रबंधन (निवेश किए गए प्रयास) का नैतिकता के साथ क्या संबंध है? जब तक मौखिक / लिखित अनुबंध पर सहमति के रूप में पूरा हो गया था।
तीज्रा

25
मुझे लगता है कि आप इस मजाक में बहुत अधिक पढ़ रहे होंगे। यह एक मजाक है कि कंप्यूटर प्रोग्रामर बुरे नैतिक निर्णय लेने के लिए कैसे आते हैं, क्योंकि वे मनुष्यों पर उनके काम के प्रभावों पर तकनीकी विचारों को प्राथमिकता देते हैं। यह कार्यक्रम डिजाइन के बारे में अच्छी सलाह होने का इरादा नहीं है।
एरिक लिपर्ट

जवाबों:


114

यह सभी तरह से नीचे कछुए है।

या इस मामले में सार।

अच्छा अभ्यास कोडिंग एक ऐसी चीज है जिसे असीम रूप से लागू किया जा सकता है, और कुछ बिंदु पर आप अमूर्त के लिए अमूर्त कर रहे हैं, जिसका अर्थ है कि आपने इसे बहुत दूर ले लिया है। उस रेखा को खोजना कुछ ऐसा नहीं है जिसे अंगूठे के नियम में रखना आसान है, क्योंकि यह आपके पर्यावरण पर बहुत निर्भर करता है।

उदाहरण के लिए, हमारे पास ऐसे ग्राहक हैं जो पहले सरल अनुप्रयोगों के लिए पूछने के लिए जाने जाते थे, लेकिन फिर विस्तार के लिए पूछते थे। हमारे पास ग्राहक भी हैं जो पूछते हैं कि वे क्या चाहते हैं और आम तौर पर विस्तार के लिए हमारे पास कभी नहीं आते हैं।
आपका दृष्टिकोण प्रति ग्राहक अलग-अलग होगा। पहले ग्राहक के लिए, यह कोड को पहले से खाली करने के लिए भुगतान करेगा क्योंकि आप यथोचित निश्चित हैं कि आपको भविष्य में इस कोड को फिर से लिखना होगा। दूसरे ग्राहक के लिए, आप उस अतिरिक्त प्रयास को निवेश नहीं करना चाह सकते हैं यदि आप उनसे अपेक्षा कर रहे हैं कि आप किसी भी बिंदु पर आवेदन का विस्तार नहीं करना चाहते हैं (ध्यान दें: इसका मतलब यह नहीं है कि आप किसी भी अच्छे अभ्यास का पालन नहीं करते हैं, लेकिन बस कि आप वर्तमान में आवश्यक से अधिक करने से बच रहे हैं ।

मुझे कैसे पता चलेगा कि किन सुविधाओं को लागू करना है?

उपरोक्त कारण का उल्लेख मैं कर रहा हूँ क्योंकि आप पहले ही इस जाल में पड़ चुके हैं:

लेकिन मुझे कैसे पता चलेगा कि कितना (और क्या) पैरामीटर बनाना है? आखिरकार, वह कह सकती है

"वह कह सकती है" वर्तमान व्यवसाय की आवश्यकता नहीं है। यह भविष्य की व्यावसायिक आवश्यकता पर एक अनुमान है। एक सामान्य नियम के रूप में, अनुमानों के आधार पर खुद को आधार न बनाएं, केवल वही विकसित करें जो वर्तमान में आवश्यक है।

हालाँकि, यहाँ संदर्भ लागू होता है। मैं तुम्हारी पत्नी को नहीं जानता। शायद आपने सही अनुमान लगाया कि वह वास्तव में यही चाहती है। लेकिन आपको अभी भी ग्राहक के साथ पुष्टि करनी चाहिए कि यह वास्तव में वही है जो वे चाहते हैं, क्योंकि अन्यथा आप एक ऐसी सुविधा विकसित करने में समय बिता रहे हैं जिसका आप कभी उपयोग नहीं कर रहे हैं।

मुझे कैसे पता चलेगा कि किस वास्तुकला को लागू करना है?

यह पेचीदा मामला है। ग्राहक आंतरिक कोड के बारे में परवाह नहीं करता है, इसलिए आप उनसे पूछ नहीं सकते कि क्या उन्हें इसकी आवश्यकता है। इस मामले पर उनकी राय ज्यादातर अप्रासंगिक है।

हालांकि, आप अभी भी ग्राहक से सही सवाल पूछकर ऐसा करने की आवश्यकता की पुष्टि कर सकते हैं । आर्किटेक्चर के बारे में पूछने के बजाय, उनसे भविष्य के विकास की उनकी अपेक्षाओं या कोडबेस के विस्तार के बारे में पूछें। आप यह भी पूछ सकते हैं कि क्या वर्तमान लक्ष्य की कोई समय सीमा है, क्योंकि आप आवश्यक समय सीमा में अपने फैंसी आर्किटेक्चर को लागू करने में सक्षम नहीं हो सकते हैं।

मुझे कैसे पता चलेगा कि कब मेरे कोड को और अमूर्त करना है?

मुझे नहीं पता कि मैं इसे कहां पढ़ता हूं (अगर किसी को पता है, मुझे बताएं और मैं इसका श्रेय दूंगा), लेकिन अंगूठे का एक अच्छा नियम यह है कि डेवलपर्स को एक गुफाओं की तरह गिनना चाहिए: एक, दो कई

यहां छवि विवरण दर्ज करें XKCD # 764

दूसरे शब्दों में, जब एक निश्चित एल्गोरिथ्म / पैटर्न का तीसरी बार उपयोग किया जा रहा है , तो इसे अमूर्त किया जाना चाहिए ताकि यह पुन: प्रयोज्य हो ( कई बार प्रयोग करने योग्य )।

बस स्पष्ट होने के लिए, मैं यह नहीं कह रहा हूं कि जब एल्गोरिदम का केवल दो उदाहरणों का उपयोग किया जा रहा है तो आपको पुन: प्रयोज्य कोड नहीं लिखना चाहिए। बेशक आप उसे भी सार कर सकते हैं, लेकिन नियम यह होना चाहिए कि तीन उदाहरणों के लिए आपको सार होना चाहिए

फिर, आपकी उम्मीदों में यह कारक। यदि आप पहले से ही जानते हैं कि आपको तीन या अधिक उदाहरणों की आवश्यकता है, तो निश्चित रूप से आप तुरंत अमूर्त कर सकते हैं। लेकिन अगर आप केवल अनुमान लगाते हैं कि आप इसे और अधिक बार लागू करना चाहते हैं, तो अमूर्त को लागू करने की शुद्धता पूरी तरह से आपके अनुमान की शुद्धता पर निर्भर करती है।
यदि आपने सही अनुमान लगाया है, तो आपने कुछ समय के लिए खुद को बचाया। यदि आपने गलत अनुमान लगाया है, तो आपने अपना कुछ समय और प्रयास बर्बाद कर दिया है और संभवतः अपनी वास्तुकला से समझौता किया है ताकि आप जिस चीज की आवश्यकता हो उसे लागू कर सकें।

अगर destroyCity(City city)तुलना में बेहतर है destroyBaghdad(), है takeActionOnCity(Action action, City city)भी बेहतर? क्यों नहीं?

यह बहुत कुछ कई बातों पर निर्भर करता है:

  • क्या ऐसे कई कार्य हैं जो किसी भी शहर पर किए जा सकते हैं ?
  • क्या इन क्रियाओं का परस्पर उपयोग किया जा सकता है? क्योंकि यदि "नष्ट" और "पुनर्निर्माण" क्रियाएं पूरी तरह से अलग-अलग निष्पादित होती हैं, तो दोनों को एक ही takeActionOnCityविधि में विलय करने का कोई मतलब नहीं है ।

इस बात से भी अवगत रहें कि यदि आप इसे संक्षिप्त करते हैं, तो आप एक ऐसी विधि के साथ समाप्त होने जा रहे हैं जो इतनी सार है कि इसमें एक और विधि को चलाने के लिए कंटेनर से ज्यादा कुछ नहीं है, जिसका अर्थ है कि आपने अपनी पद्धति को अप्रासंगिक और निरर्थक बना दिया है।
यदि आपकी पूरी takeActionOnCity(Action action, City city)विधि निकाय से अधिक कुछ नहीं है action.TakeOn(city);, तो आपको आश्चर्य होना चाहिए कि क्या takeActionOnCityविधि का वास्तव में कोई उद्देश्य है या केवल एक अतिरिक्त परत नहीं है जो मूल्य का कुछ भी नहीं जोड़ता है।

लेकिन शहरों पर कार्रवाई करना मेरे लिए पर्याप्त नहीं है, कैसे takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea)?

एक ही सवाल यहाँ पॉप:

  • क्या आपके पास भौगोलिक क्षेत्रों के लिए उपयोग का मामला है?
  • क्या एक शहर और एक क्षेत्र पर एक कार्रवाई का निष्पादन एक ही है?
  • क्या किसी भी क्षेत्र / शहर पर कोई कार्रवाई की जा सकती है?

यदि आप निश्चित रूप से तीनों को "हां" का जवाब दे सकते हैं, तो एक अमूर्त वारंट है।


16
मैं "एक, दो, कई" नियम पर जोर नहीं दे सकता। कुछ को अमूर्त / पैराट्रिएज़ करने की अनंत संभावनाएं हैं, लेकिन उपयोगी उपसमुच्चय छोटा है, अक्सर शून्य है। यह जानना कि किस संस्करण का मूल्य सबसे अधिक है अक्सर केवल पूर्वव्यापी में निर्धारित किया जा सकता है। तो तत्काल आवश्यकताओं * से चिपके रहें और नई आवश्यकताओं या बाधा से आवश्यकतानुसार जटिलता जोड़ें। * कभी-कभी आप समस्या स्थान को अच्छी तरह से जानते हैं, तो कुछ जोड़ने के लिए ठीक हो सकता है क्योंकि आपको पता है कि आपको कल इसकी आवश्यकता है। लेकिन इस शक्ति का बुद्धिमानी से उपयोग करें, इससे बर्बादी भी हो सकती है।
क्रिश्चियन सॉयर

2
> "मुझे नहीं पता कि मैंने इसे कहां पढ़ा है [..]"। आप कोडिंग हॉरर: द रूल ऑफ थ्री पढ़ रहे होंगे ।
रूण

10
"एक, दो, कई नियम" वास्तव में DRY आँख बंद करके गलत अमूर्त निर्माण से रोकने के लिए है। बात यह है कि, कोड के दो टुकड़े लगभग समान दिखने लग सकते हैं, इसलिए यह मतभेदों को दूर करने के लिए आकर्षक है; लेकिन जल्दी से, आप नहीं जानते कि कोड के कौन से भाग स्थिर हैं, और कौन से नहीं हैं; इसके अलावा, यह पता चला है कि उन्हें वास्तव में स्वतंत्र रूप से विकसित होने की आवश्यकता है (विभिन्न परिवर्तन पैटर्न, जिम्मेदारियों के विभिन्न सेट)। या तो मामले में, एक गलत अमूर्त आपके खिलाफ काम करता है और रास्ते में हो जाता है।
फिलिप मिलोवानोविक

4
"एक ही तर्क" के दो से अधिक उदाहरणों की प्रतीक्षा करना आपको एक बेहतर न्यायाधीश होने की अनुमति देता है कि क्या सार होना चाहिए, और कैसे (और वास्तव में, यह विभिन्न परिवर्तनों के साथ कोड के बीच निर्भरता / युग्मन के प्रबंधन के बारे में है)।
फिलिप मिलोवानोविक

1
@kukis: यथार्थवादी रेखा को 2 पर खींचा जाना चाहिए (बाल्ड्रिक की टिप्पणी के अनुसार): शून्य-एक-कई (डेटाबेस संबंधों के लिए मामला है)। हालाँकि, यह व्यवहार की मांग करने वाले अनावश्यक पैटर्न के लिए द्वार खोलता है। दो चीजें अस्पष्ट रूप से एक जैसी दिख सकती हैं लेकिन इसका मतलब यह नहीं है कि वे वास्तव में समान हैं। हालांकि, जब तीसरा उदाहरण मैदान में प्रवेश करता है जो पहले और दूसरे उदाहरण दोनों से मिलता-जुलता है, तो आप अधिक सटीक निर्णय ले सकते हैं कि उनकी समानताएं वास्तव में पुन: प्रयोज्य पैटर्न हैं। तो सामान्य ज्ञान रेखा 3 पर खींची गई है, जो केवल दो उदाहरणों के बीच "पैटर्न" को खोलते समय मानवीय त्रुटि के कारक हैं।
फ्लेटर

44

अभ्यास

यह सॉफ्टवेयर इंजीनियरिंग एसई है, लेकिन सॉफ्टवेयर का क्राफ्टिंग इंजीनियरिंग की तुलना में बहुत अधिक कला है। कितना पुन: प्रयोज्यता पर्याप्त है, यह पता लगाने के लिए अनुसरण करने या मापने के लिए कोई सार्वभौमिक एल्गोरिथ्म नहीं है। किसी भी चीज़ की तरह, जितना अधिक अभ्यास आप डिजाइनिंग प्रोग्राम प्राप्त करते हैं उतना बेहतर होगा कि आप उस पर प्राप्त करेंगे। आपको यह महसूस करने के लिए बेहतर होगा कि "पर्याप्त" क्या है क्योंकि आप देखेंगे कि क्या गलत है और कैसे गलत हो जाता है जब आप बहुत अधिक या बहुत कम पैरामीटर करते हैं।

यही कारण है कि बहुत उपयोगी नहीं है अब हालांकि, तो कैसे कुछ दिशा निर्देश के बारे में?

अपने प्रश्न पर वापस देखो। "वह कह सकती है" और "मैं कर सकती थी" का एक बहुत कुछ है। भविष्य की कुछ जरूरतों के बारे में बहुत सारे कथन। इंसान भविष्य की भविष्यवाणी करने में कतराता है। और आप (सबसे अधिक संभावना) एक मानव हैं। सॉफ़्टवेयर डिज़ाइन की अत्यधिक समस्या एक ऐसे भविष्य के लिए जिम्मेदार है, जिसे आप नहीं जानते हैं।

दिशानिर्देश 1: आपको इसकी आवश्यकता नहीं है

गंभीरता से। अभी रोको। अधिक बार नहीं, भविष्य की समस्या की कल्पना दिखाई नहीं देती है - और यह निश्चित रूप से वैसा नहीं दिखाई देगा जैसा आपने कल्पना की थी।

दिशानिर्देश 2: लागत / लाभ

कूल, उस छोटे से प्रोग्राम को शायद आपको लिखने में कुछ घंटे लगे? तो क्या हुआ अगर आपकी पत्नी है वापस आने के लिए और उन चीजों के लिए पूछना? सबसे खराब स्थिति, आप इसे करने के लिए एक और कार्यक्रम के साथ कुछ और घंटे खर्च करते हैं। इस मामले के लिए, इस कार्यक्रम को अधिक लचीला बनाने के लिए बहुत अधिक समय नहीं है। और यह रनटाइम स्पीड या मेमोरी उपयोग के लिए बहुत कुछ जोड़ने वाला नहीं है। लेकिन गैर-तुच्छ कार्यक्रमों के अलग-अलग उत्तर हैं। अलग-अलग परिदृश्यों के अलग-अलग उत्तर हैं। कुछ बिंदु पर, लागत स्पष्ट रूप से अपूर्ण भविष्य बताने के कौशल के साथ भी लाभ के लायक नहीं है।

दिशानिर्देश 3: स्थिरांक पर ध्यान दें

प्रश्न पर वापस देखें। आपके मूल कोड में, निरंतर बहुत सारे इनट्स हैं। 2018, 1। लगातार आवक, लगातार तार ... वे सबसे अधिक संभावना चीजें हैं जो निरंतर नहीं होने की आवश्यकता है । बेहतर अभी तक, उन्हें केवल (या कम से कम वास्तविक स्थिरांक के रूप में परिभाषित करने के लिए) थोड़ा समय लगता है। लेकिन एक और चीज से सावधान रहना निरंतर व्यवहार हैSystem.out.printlnउदाहरण के लिए। उपयोग के बारे में इस तरह की धारणा भविष्य में बदलती है और ठीक करने के लिए बहुत महंगा हो जाता है। इतना ही नहीं, लेकिन इस तरह IO फ़ंक्शन को अशुद्ध बनाता है (कुछ समय के लिए समय के साथ साथ)। उस व्यवहार को परिमाणित करने से कार्य अधिक शुद्ध हो सकता है जिससे लचीलापन और परीक्षण क्षमता बढ़ सकती है। न्यूनतम लागत के साथ बड़े लाभ (विशेषकर यदि आप एक अधिभार बनाते हैं जो System.outडिफ़ॉल्ट रूप से उपयोग करता है)।


1
यह सिर्फ एक दिशानिर्देश है, 1s ठीक है, लेकिन आप उन्हें देखते हैं और "क्या यह कभी बदलेगा?" नहीं। और Println को एक उच्च क्रम फ़ंक्शन के साथ परिचालित किया जा सकता है - हालांकि जावा उन पर महान नहीं है।
तेलस्तीन

5
@KorayTugay: यदि कार्यक्रम वास्तव में आपकी पत्नी के घर पर आने के लिए था, तो YAGNI आपको बताएगा कि आपका प्रारंभिक संस्करण एकदम सही है, और आपको स्थिरांक या मापदंडों को पेश करने के लिए किसी भी अधिक समय का निवेश नहीं करना चाहिए। YAGNI को संदर्भ की आवश्यकता है - क्या आपका कार्यक्रम एक फेंक-दूर का समाधान है, या कुछ महीनों के लिए केवल एक प्रवास कार्यक्रम चलता है, या यह एक विशाल ईआरपी प्रणाली का हिस्सा है, जिसका उपयोग कई दशकों से किया जाता है और बनाए रखा जाता है?
डॉक्टर ब्राउन

8
@KorayTugay: गणना से I / O को अलग करना एक मौलिक कार्यक्रम संरचना तकनीक है। डेटा की प्रस्तुति से डेटा की खपत से डेटा के परिवर्तन से डेटा की पीढ़ी को अलग करना। आपको कुछ कार्यात्मक कार्यक्रमों का अध्ययन करना चाहिए, फिर आप इसे अधिक स्पष्ट रूप से देखेंगे। कार्यात्मक प्रोग्रामिंग में, डेटा की एक अनंत राशि उत्पन्न करना काफी आम है, केवल उस डेटा को फ़िल्टर करें जिसमें आप रुचि रखते हैं, डेटा को आपके द्वारा आवश्यक प्रारूप में रूपांतरित करें, उसमें से एक स्ट्रिंग का निर्माण करें, और इस स्ट्रिंग को 5 अलग-अलग कार्यों में प्रिंट करें, प्रत्येक चरण के लिए एक।
जोर्ग डब्ल्यू मित्तग

3
एक सिडेनोट के रूप में, YAGNI का दृढ़ता से पालन करने से निरंतर रिफ्लेक्टर की आवश्यकता होती है: " निरंतर रिफैक्टिंग के बिना उपयोग किया जाता है, इससे अव्यवस्थित कोड और बड़े पैमाने पर कार्य हो सकता है, जिसे तकनीकी ऋण के रूप में जाना जाता है।" इसलिए जब YAGNI सामान्य रूप से एक अच्छी बात है, तो यह कोड के पुनरीक्षण और पुनर्मूल्यांकन की एक बड़ी जिम्मेदारी के साथ आता है, जो कि हर डेवलपर / कंपनी ऐसा करने के लिए तैयार नहीं है।
फ्लेटर

4
@Telastyn: मैं इस सवाल का विस्तार करने का सुझाव देता हूं कि "क्या यह कभी नहीं बदलेगा और निरंतर नाम लिए बिना कोड का उद्देश्य केवल पठनीय है ?" यहां तक ​​कि उन मूल्यों के लिए जो कभी नहीं बदलते हैं, उन्हें केवल पठनीय चीजों को रखने के लिए उनका नाम देना प्रासंगिक हो सकता है।
फ्लोटर

27

सबसे पहले: कोई भी सुरक्षा दिमाग वाला सॉफ्टवेयर डेवलपर किसी भी कारण से एक प्राधिकरण टोकन को पारित किए बिना एक विध्वंस विधि नहीं लिखेगा।

मैं भी एक अनिवार्यता के रूप में कुछ भी लिख सकता हूं, जिसके बारे में स्पष्ट है कि इसके बिना किसी अन्य संदर्भ में लागू किया जा सकता है। एक स्ट्रिंग संयोजन को अधिकृत करना क्यों आवश्यक है?

दूसरी बात: निष्पादित होने पर सभी कोड पूरी तरह से निर्दिष्ट होने चाहिए

इससे कोई फर्क नहीं पड़ता कि निर्णय जगह में कठिन कोडित था, या किसी अन्य परत को स्थगित कर दिया गया था। कुछ बिंदु पर कुछ भाषा में एक कोड होता है जो जानता है कि दोनों को क्या नष्ट करना है और इसे कैसे निर्देश देना है।

यह एक ही ऑब्जेक्ट फ़ाइल में हो सकता है destroyCity(xyz), और यह एक कॉन्फ़िगरेशन फ़ाइल में हो सकता है: destroy {"city": "XYZ"}"या यह एक UI में क्लिक और कीबोर्ड की एक श्रृंखला हो सकती है।

तीसरा:

हनी .. क्या आप कंसोल में 2018 के लिए दुनिया भर के सभी डे लाइट सेविंग प्रिंट कर सकते हैं? मुझे कुछ जांचने की जरूरत है।

आवश्यकताओं का एक बहुत अलग सेट है:

वह एक कस्टम स्ट्रिंग फ़ॉर्मेटर पास करना चाहती है, ... केवल कुछ निश्चित महीनों में रुचि रखती है, ... [और] कुछ घंटों की अवधि में रुचि ...

अब आवश्यकताओं का दूसरा सेट स्पष्ट रूप से अधिक लचीले उपकरण के लिए बनाता है। इसमें व्यापक लक्षित श्रोता और अनुप्रयोग का एक व्यापक क्षेत्र है। यहां खतरा यह है कि दुनिया में सबसे लचीला अनुप्रयोग वास्तव में मशीन कोड के लिए एक संकलक है। यह वस्तुतः एक प्रोग्राम है इसलिए यह सामान्य है कि कंप्यूटर को बनाने के लिए कुछ भी निर्माण किया जा सकता है जिसे आपको इसकी आवश्यकता है (इसके हार्डवेयर की बाधाओं के भीतर)।

आम तौर पर बोलने वाले लोग जिन्हें सॉफ्टवेयर की आवश्यकता होती है, वे कुछ सामान्य नहीं चाहते हैं; वे कुछ विशिष्ट चाहते हैं। अधिक विकल्प देकर आप वास्तव में अपने जीवन को और अधिक जटिल बना रहे हैं। यदि वे उस जटिलता को चाहते थे, तो वे आपसे पूछने के बजाय एक कंपाइलर का उपयोग कर रहे होंगे।

आपकी पत्नी कार्यक्षमता के लिए पूछ रही थी, और अपनी आवश्यकताओं को आपके अधीन कर दिया। इस मामले में यह उद्देश्य पर प्रतीत होता था, और सामान्य तौर पर यह इसलिए है क्योंकि वे किसी भी बेहतर नहीं जानते हैं। अन्यथा वे केवल संकलक का उपयोग करते थे। तो पहली समस्या यह है कि आप इसके बारे में अधिक जानकारी नहीं माँगते कि वह क्या करना चाहती है। क्या वह इसे कई अलग-अलग वर्षों से चलाना चाहती थी? क्या वह इसे सीएसवी फ़ाइल में चाहती थी? आपको यह पता नहीं चला कि वह अपने आप को क्या निर्णय देना चाहती थी, और क्या वह आपसे यह पता लगाने और उसके लिए निर्णय लेने के लिए कह रही थी। एक बार जब आपको पता चल गया कि किन फैसलों को स्थगित करने की आवश्यकता है, तो आप यह पता लगा सकते हैं कि मापदंडों (और अन्य विन्यास साधनों) के माध्यम से उन निर्णयों को कैसे संवाद किया जाए।

यह कहा जा रहा है, अधिकांश ग्राहक कुछ विवरणों (उर्फ निर्णयों) से अनभिज्ञ, मिस-कम्यूनिकेट या अनजान होते हैं, जिसे वे वास्तव में स्वयं बनाना चाहते हैं, या कि वे वास्तव में बनाना नहीं चाहते हैं (लेकिन यह बहुत अच्छा लगता है) यही कारण है कि पीडीएसए (योजना-विकास-अध्ययन-अधिनियम) जैसे काम के तरीके महत्वपूर्ण हैं। आपने आवश्यकताओं के अनुरूप कार्य की योजना बनाई है, और फिर आपने निर्णय (कोड) का एक सेट विकसित किया है। अब इसका अध्ययन करने का समय है, या तो अपने या अपने ग्राहक के साथ और नई चीजें सीखें, और ये आपकी सोच को आगे बढ़ाते हैं। अंत में अपने नए अंतर्दृष्टि पर कार्य करें - आवश्यकताओं को अपडेट करें, प्रक्रिया को परिष्कृत करें, नए उपकरण प्राप्त करें, आदि ... फिर योजना फिर से शुरू करें। यह समय के साथ किसी भी छिपी आवश्यकताओं को प्रकट करता है, और कई ग्राहकों के लिए प्रगति को साबित करता है।

आखिरकार। आपका समय महत्वपूर्ण है ; यह बहुत वास्तविक है और बहुत परिमित है। आपके द्वारा किया गया प्रत्येक निर्णय कई अन्य छिपे हुए निर्णयों को उलझा देता है, और यही वह है जो विकासशील सॉफ्टवेयर के बारे में है। एक निर्णय के रूप में एक तर्क में देरी करने से वर्तमान फ़ंक्शन सरल हो सकता है, लेकिन यह कहीं और अधिक जटिल बनाता है। क्या यह निर्णय उस अन्य स्थान पर प्रासंगिक है? क्या यह यहाँ अधिक प्रासंगिक है? वास्तव में यह किसका निर्णय लेना है? यह आप तय कर रहे हैं; यह कोडिंग है। यदि आप अक्सर निर्णय के सेट को दोहराते हैं, तो कुछ अमूर्त के अंदर उन्हें कोडित करने में बहुत वास्तविक लाभ होता है। XKCD का यहाँ एक उपयोगी दृष्टिकोण है। और यह एक प्रणाली के स्तर पर प्रासंगिक है यह एक फ़ंक्शन, मॉड्यूल, प्रोग्राम आदि है।

शुरू में सलाह का अर्थ है कि आपके निर्णय को निर्णय लेने का कोई अधिकार नहीं है कि एक तर्क के रूप में पारित किया जाना चाहिए। समस्या यह है कि एक DestroyBaghdadफ़ंक्शन वास्तव में ऐसा फ़ंक्शन हो सकता है जिसमें वह अधिकार है।


+1 संकलक के बारे में प्यार करता हूँ!
ली

4

यहां बहुत लंबे घुमावदार उत्तर हैं, लेकिन ईमानदारी से मुझे लगता है कि यह सुपर सरल है

आपके पास अपने फ़ंक्शन में कोई भी हार्ड कोडित जानकारी जो फ़ंक्शन नाम का हिस्सा नहीं है, एक पैरामीटर होना चाहिए।

आपके फंक्शन में

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(zoneId -> {
            LocalDateTime dateTime = LocalDateTime.of(LocalDate.of(2018, 1, 1), LocalTime.of(0, 0, 0));
            ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
            while (2018 == now.getYear()) {
                int hour = now.getHour();
                now = now.plusHours(1);
                if (now.getHour() == hour) {
                    System.out.println(now);
                }
            }
        });
    }
}

आपके पास:

The zoneIds
2018, 1, 1
System.out

इसलिए मैं इन सभी को एक या दूसरे रूप में मापदंडों पर ले जाऊंगा। आप यह तर्क दे सकते हैं कि जोनआईड्स फ़ंक्शन के नाम में निहित हैं, शायद आप इसे "डेलाइटस्वाइनसंग ऑवरइनवर्ल्ड" या कुछ और के रूप में बदलना चाहते हैं।

आपके पास एक प्रारूप स्ट्रिंग नहीं है, इसलिए एक जोड़ना एक सुविधा अनुरोध है और आपको अपनी पत्नी को अपने परिवार के जीरा उदाहरण के लिए संदर्भित करना चाहिए। इसे बैकलॉग पर रखा जा सकता है और उपयुक्त परियोजना प्रबंधन समिति की बैठक में प्राथमिकता दी जा सकती है।


1
आप (ओपी को खुद को संबोधित करते हुए) निश्चित रूप से एक प्रारूप स्ट्रिंग नहीं जोड़ना चाहिए, क्योंकि आपको कुछ भी प्रिंट नहीं करना चाहिए। इस कोड के बारे में एक बात जो इसके पुन: उपयोग को रोकती है, वह है प्रिंट। जब वे डीएसटी से बाहर जाते हैं, तो उन्हें ज़ोन, या ज़ोन का एक नक्शा वापस करना चाहिए। (हालांकि यह डीएसटी से दूर जाने पर ही इसकी पहचान करता है , और डीएसटी पर नहीं , मुझे समझ में नहीं आता है। यह समस्या के बयान से मेल नहीं खाता है।)
डेविड कॉनराड

आवश्यकता सांत्वना के लिए मुद्रित करने के लिए है। आप एक पैरामीटर के रूप में आउटपुट स्ट्रीम में पास करके तंग कप्लुंग को कम कर सकते हैं जैसा कि मैं सुझाव देता हूं
ईवान

1
फिर भी, यदि आप चाहते हैं कि कोड पुन: प्रयोज्य हो, तो आपको कंसोल पर प्रिंट नहीं करना चाहिए। एक विधि लिखें जो परिणाम लौटाती है, और फिर एक कॉलर लिखें जो उन्हें और प्रिंट करता है। यह भी परीक्षण करने योग्य बनाता है। यदि आप इसे उत्पादन करना चाहते हैं, तो मैं एक आउटपुट स्ट्रीम में पास नहीं करूंगा, मैं एक उपभोक्ता में पास हो जाऊंगा।
डेविड कॉनरेड

एक ourput स्ट्रीम एक उपभोक्ता है
इवान

नहीं, एक OutputStream उपभोक्ता नहीं है ।
डेविड कॉनरेड

4

संक्षेप में, अपने सॉफ़्टवेयर को पुन: प्रयोज्यता के लिए इंजीनियर न करें क्योंकि कोई अंतिम उपयोगकर्ता परवाह नहीं करता है यदि आपके कार्यों का पुन: उपयोग किया जा सकता है। इसके बजाय, डिजाइन की समझ के लिए इंजीनियर - क्या मेरा कोड किसी और के लिए आसान है या मेरे भविष्य को समझने में स्वयं को भूल गया है? - और डिजाइन लचीलापन- जब मुझे अनिवार्य रूप से बग्स को ठीक करना होगा, सुविधाओं को जोड़ना होगा, या अन्यथा कार्यक्षमता को संशोधित करना होगा, तो मेरा कोड परिवर्तनों का विरोध कैसे करेगा? आपके ग्राहक की एकमात्र बात यह है कि जब वह बग की रिपोर्ट करता है या बदलाव के लिए पूछता है तो आप कितनी जल्दी प्रतिक्रिया दे सकते हैं। अपने डिजाइन के बारे में ये प्रश्न पूछना संयोग से कोड में परिणाम है कि पुन: प्रयोज्य है, लेकिन यह दृष्टिकोण आपको उस कोड के जीवन पर आने वाली वास्तविक समस्याओं से बचने पर ध्यान केंद्रित करता है ताकि आप उदात्त, अव्यवहारिक का पीछा करने के बजाय अंत उपयोगकर्ता की बेहतर सेवा कर सकें। गर्दन-दाढ़ी को खुश करने के लिए "इंजीनियरिंग" आदर्श।

आपके द्वारा दिए गए उदाहरण के रूप में सरल रूप में कुछ के लिए, आपका प्रारंभिक कार्यान्वयन ठीक है क्योंकि यह कितना छोटा है, लेकिन यह सीधा डिजाइन समझना और भंगुर हो जाएगा यदि आप बहुत अधिक कार्यात्मक लचीलेपन को जाम करने की कोशिश करते हैं (जैसा कि डिजाइन लचीलेपन के विपरीत)। एक प्रक्रिया। नीचे समझ और लचीलेपन के लिए जटिल प्रणालियों को डिजाइन करने के लिए मेरे पसंदीदा दृष्टिकोण की मेरी व्याख्या है जो मुझे आशा है कि मैं उनके द्वारा क्या मतलब दिखाऊंगा। मैं इस रणनीति को किसी ऐसी चीज के लिए नियोजित नहीं करूंगा, जो एक ही प्रक्रिया में 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खुद के बाहर के आंतरिक कामकाज का अंतरंग ज्ञान तंग युग्मन होगा जो कम कर देता है felxibility चूंकि आपको उन बाहरी तत्वों पर विचार करना है, जिनके लिए आपको कभी भी व्यवहार को संशोधित करने की आवश्यकता होगी 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);
    }
}

ObjectsByRadiusBombइनपुट्स से गणना की गई वस्तुओं का एक समूह का प्रतिनिधित्व Bombकरता है क्योंकि इस बात की परवाह नहीं करता है कि गणना कितनी लंबी है, क्योंकि यह वस्तुओं के साथ काम कर सकता है। यह पुन: प्रयोज्य रूप से संयोगवश होता है, लेकिन मुख्य लक्ष्य यह है कि गणना को छोड़ने Bombऔर वस्तुओं को नष्ट करने की प्रक्रियाओं से अलग किया जाए ताकि आप प्रत्येक टुकड़े को समझ सकें और कैसे वे एक साथ फिट होते हैं और पूरे एल्गोरिथ्म को फिर से व्यवस्थित किए बिना एक व्यक्तिगत टुकड़े के व्यवहार को बदल सकते हैं। ।

सहभागिता, एल्गोरिदम नहीं

एक जटिल एल्गोरिथ्म के लिए मापदंडों की सही संख्या का अनुमान लगाने की कोशिश करने के बजाय, यह प्रक्रिया को मॉडल करने के लिए और अधिक अर्थ देता है बातचीत की वस्तुओं के एक सेट के रूप में, प्रत्येक अत्यंत संकीर्ण भूमिकाओं के साथ, क्योंकि यह आपको अपनी जटिलता को मॉडल करने की क्षमता देगा। इन अच्छी तरह से परिभाषित, समझने में आसान और लगभग अपरिवर्तित वस्तुओं के बीच बातचीत के माध्यम से प्रक्रिया। जब सही ढंग से किया जाता है, तो यह कुछ सबसे जटिल संशोधनों को भी तुच्छ बना देता है जैसा कि एक इंटरफ़ेस या दो को लागू करना और जो आपके ऑब्जेक्ट को तुरंत लागू करते हैं main()

मैं आपको अपने मूल उदाहरण के लिए कुछ देता हूँ, लेकिन मैं ईमानदारी से यह नहीं समझ सकता कि इसका "प्रिंट ... डे लाइट सेविंग" का क्या मतलब है। समस्या की उस श्रेणी के बारे में मैं क्या कह सकता हूं कि किसी भी समय आप एक गणना कर रहे हैं, जिसके परिणाम स्वरूप कई तरीके तैयार किए जा सकते हैं, मेरा पसंदीदा तरीका यह है कि इस तरह से नीचे गिरा जाए:

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सीधे एपीआई का उपयोग कर सकते हैं। यहाँ विचार यह है कि प्रत्येक गणना अपनी ही वस्तु के भीतर कूटबद्ध है। यह इस बारे में कोई धारणा नहीं बनाता है कि इसे कितनी बार चलाना चाहिए या परिणाम को कैसे प्रारूपित करना चाहिए। यह विशेष रूप से गणना का सबसे सरल रूप प्रदर्शन करने से संबंधित है। इससे इसे समझना और बदलना दोनों आसान हो जाता है। इसी तरह, Resultविशेष रूप से गणना के परिणाम को एनकैप्सुलेट करने से संबंधित है, और FormattedResultविशेष रूप से 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()
            );
        });
    }
}

तथ्य की बात के रूप में, ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को विशेष रूप से इंपीरियल प्रतिमान की जटिलता / लचीलेपन की समस्या के समाधान के रूप में आविष्कार किया गया था क्योंकि वहाँ कोई अच्छा जवाब नहीं है (कि हर कोई स्वतंत्र रूप से किसी भी तरह सहमत हो सकता है या पहुंच सकता है) मुहावरे के भीतर शाही कार्यों और प्रक्रियाओं को निर्दिष्ट करें।


यह एक बहुत विस्तृत और विचारशील उत्तर है, लेकिन दुर्भाग्य से मुझे लगता है कि यह उस निशान को याद करता है जो ओपी वास्तव में पूछ रहा था। वह अपने विशिष्ट उदाहरण को हल करने के लिए अच्छे OOP प्रथाओं पर एक सबक के लिए नहीं पूछ रहा था, वह उन मानदंडों के बारे में पूछ रहा था जहां हम एक समाधान बनाम सामान्यीकरण में समय के निवेश का निर्णय लेते हैं।
maple_shaft

@maple_shaft शायद मैं निशान से चूक गया, लेकिन मुझे लगता है कि आपके पास भी है। ओपी समय बनाम सामान्यीकरण के निवेश के बारे में नहीं पूछता है। वह पूछता है "मुझे कैसे पता चलेगा कि मेरे तरीके कैसे पुन: प्रयोज्य होने चाहिए?" वह अपने सवाल के शरीर में पूछने के लिए आगे बढ़ता है, "अगर विध्वंस (शहर शहर) को नष्ट करने से बेहतर है तो बाधागढ़ (), क्या टेकऑनऑनसिटी (एक्शन एक्शन, सिटी सिटी) और भी बेहतर है? क्यों / क्यों नहीं?" मैंने इंजीनियरिंग समाधानों के लिए एक वैकल्पिक दृष्टिकोण के लिए मामला बनाया है कि मेरा मानना ​​है कि तरीकों का पता लगाने की समस्या हल करने की समस्या का हल है और मेरे दावे का समर्थन करने के लिए उदाहरण प्रदान किए हैं। मुझे खेद है कि आपको यह पसंद नहीं आया।
स्तूपरमैन

@maple_shaft सच कहूँ तो, केवल ओपी ही यह निश्चय कर सकता है कि मेरा उत्तर उसके प्रश्न के लिए प्रासंगिक था क्योंकि हम में से बाकी लोग अपने इरादों की हमारी व्याख्याओं का बचाव करने वाले युद्ध लड़ सकते थे, जिनमें से सभी समान रूप से गलत हो सकते हैं।
स्टुपोर्मैन

@maple_shaft मैंने यह पूछने के लिए कि यह कैसे प्रश्न से संबंधित है और उत्तर और उदाहरण कार्यान्वयन के बीच एक स्पष्ट परिसीमन प्रदान करने का प्रयास करने के लिए एक परिचय जोड़ा। क्या वो बेहतर है?
स्तूपरमैन

1
ईमानदारी से, यदि आप इन सभी सिद्धांतों को लागू करते हैं, तो उत्तर स्वाभाविक रूप से, सहज और व्यापक रूप से पठनीय होगा। इसके अलावा, बहुत उपद्रव के बिना अस्थिर। मैं नहीं जानता कि आप कौन हैं, लेकिन मैं चाहता हूं कि आप में से अधिक था! मैं सभ्य OO के लिए प्रतिक्रियाशील कोड को बाहर निकालता रहता हूं, और यह हमेशा आधे आकार, अधिक पठनीय, अधिक नियंत्रणीय और फिर भी थ्रेडिंग / विभाजन / मैपिंग करता है। मुझे लगता है कि रिएक्ट उन लोगों के लिए है जो "बुनियादी" अवधारणाओं को नहीं समझते हैं जिन्हें आपने अभी सूचीबद्ध किया है।
स्टीफन जे

3

अनुभव , डोमेन ज्ञान , और कोड समीक्षा।

और, चाहे आपके पास कितना या कितना कम अनुभव , डोमेन ज्ञान , या टीम हो, आप जरूरत के रूप में रिफ्लेक्टर की आवश्यकता से बच नहीं सकते हैं


अनुभव के साथ , आप अपने लिखे गए डोमेन-निरर्थक तरीकों (और कक्षाओं) में पैटर्न को पहचानना शुरू करेंगे। और, यदि आप DRY कोड में रुचि रखते हैं, तो आपको बुरी भावनाएं महसूस होंगी जब आप एक ऐसी विधि के बारे में लिखेंगे, जिसे आप सहज रूप से जानते हैं कि आप भविष्य में बदलाव लिखेंगे। तो, आप सहजता से इसके बजाय एक पैरामीरिज कम से कम सामान्य भाजक लिखेंगे।

(यह अनुभव आपके कुछ डोमेन ऑब्जेक्ट्स और विधियों में भी सहज रूप से स्थानांतरित हो सकता है।)

डोमेन नॉलेज के साथ , आपके पास एक समझ होगी जिसके लिए व्यावसायिक अवधारणाएं निकट से संबंधित हैं, किन अवधारणाओं के चर हैं, जो काफी स्थिर हैं, आदि।

कोड समीक्षा के साथ, उत्पादन कोड बनने से पहले अंडर और ओवर-पैराडाइजेशन की संभावना अधिक हो जाएगी, क्योंकि आपके साथियों के पास डोमेन (सामान्य रूप से) और कोडिंग दोनों में अद्वितीय अनुभव और दृष्टिकोण होंगे


उस ने कहा, नए डेवलपर्स के पास आमतौर पर इन स्पाइडी सेन्स या साथियों का एक अनुभवी समूह नहीं होगा जो तुरंत झुक जाए। और, यहां तक ​​कि अनुभवी डेवलपर्स नई आवश्यकताओं के माध्यम से या मस्तिष्क-धूमिल दिनों के माध्यम से मार्गदर्शन करने के लिए एक मूल अनुशासन से लाभ उठाते हैं। तो, यहाँ मैं एक शुरुआत के रूप में क्या सुझाव दूंगा :

  • कम से कम पैरामीरीज़ेशन के साथ, भोले कार्यान्वयन के साथ शुरू करें।
    (किसी भी पैरामीटर को शामिल करें जो आपको पहले से ही पता है कि आपको आवश्यकता होगी, जाहिर है ...)
  • मैजिक नंबर और स्ट्रिंग्स निकालें, उन्हें कॉन्फ़िगर और / या मापदंडों पर ले जाएं
  • फैक्टर "बड़े" तरीके छोटे, अच्छी तरह से नामित विधियों में नीचे हैं
  • एक आम भाजक में परावर्तक अत्यधिक निरर्थक विधियाँ (यदि सुविधाजनक हो), अंतरों को पैरामीट्रिक कर देती हैं।

ये चरण आवश्यक रूप से बताए गए क्रम में नहीं होते हैं। यदि आप एक विधि लिखने के लिए बैठते हैं, जिसे आप पहले से ही एक मौजूदा विधि के साथ अत्यधिक अनावश्यक जानते हैं , तो सुविधाजनक होने पर सीधे रिफैक्टिंग में कूदें (यदि इसे रिफ्लैक्टर में ज्यादा समय नहीं लगेगा, तो यह सिर्फ लिखने, परीक्षण करने और दो तरीकों को बनाए रखने के लिए होगा।)

लेकिन, सिर्फ अनुभव और बहुत आगे होने के अलावा, मैं बहुत कम से कम कोड DRY-ing सलाह देता हूं। स्पष्ट उल्लंघनों का खंडन करना कठिन नहीं है। और, अगर आप बहुत अधिक ईर्ष्या करते हैं, तो आप "ओवर-डीआरवाई" कोड के साथ समाप्त हो सकते हैं जो "डब्ल्यूईटी" समकक्ष की तुलना में पढ़ना, समझना और बनाए रखना कठिन है।


2
तो इसका कोई सही जवाब नहीं है If destoryCity(City city) is better than destoryBaghdad(), is takeActionOnCity(Action action, City city) even better?? यह एक हाँ / नहीं सवाल है, लेकिन इसका जवाब नहीं है, है ना? या प्रारंभिक धारणा गलत है, destroyCity(City)शायद बेहतर होना जरूरी नहीं है और यह वास्तव में निर्भर करता है ? तो इसका मतलब यह नहीं है कि मैं नैतिक रूप से प्रशिक्षित सॉफ्टवेयर इंजीनियर नहीं हूं क्योंकि मैंने सीधे किसी पैरामीटर के बिना पहले स्थान पर लागू किया है? मेरा मतलब है कि मैं जो ठोस सवाल पूछ रहा हूं उसका जवाब क्या है?
कोरे तुगे

आपका प्रश्न कुछ प्रश्न पूछता है। शीर्षक प्रश्न का उत्तर है, "अनुभव, डोमेन ज्ञान, कोड समीक्षा ... और ... रिफ्लेक्टर से डरो मत।" किसी भी ठोस का जवाब "विधि एबीसी के लिए ये सही मानदंड हैं" सवाल है ... "मुझे नहीं पता। आप क्यों पूछ रहे हैं? क्या वर्तमान में जितने पैरामीटर हैं उनके साथ कुछ गलत है ??? यदि ऐसा है, तो स्पष्ट करें इसे ठीक करो। " ... मैं आपको आगे के मार्गदर्शन के लिए "पीओएपी" का उल्लेख कर सकता हूं : आपको यह समझने की आवश्यकता है कि आप जो कर रहे हैं वह क्यों कर रहे हैं!
svidgen

मेरा मतलब है ... चलो भी destroyBaghdad()विधि से एक कदम पीछे हटें। क्या संदर्भ है? क्या यह एक वीडियो गेम है जहाँ खेल के अंत में बगदाद नष्ट हो जाता है ??? यदि ऐसा है ... destroyBaghdad()एक पूरी तरह से उचित विधि का नाम / हस्ताक्षर हो सकता है ...
svidgen

1
तो आप मेरे प्रश्न में उद्धृत उद्धरण से सहमत नहीं हैं, है ना? It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure.यदि आप नथानिएल बोरेंस्टीन के साथ कमरे में थे, तो आप उनसे बहस करेंगे कि यह वास्तव में निर्भर करता है और उनका कथन सही नहीं है? मेरा मतलब है कि यह सुंदर है कि बहुत से लोग जवाब दे रहे हैं, अपना समय और ऊर्जा खर्च कर रहे हैं, लेकिन मुझे कहीं भी एक भी ठोस जवाब नहीं दिख रहा है। स्पाइडी-सेंस, कोड समीक्षाएं .. लेकिन इसका जवाब क्या है is takeActionOnCity(Action action, City city) better? null?
कोरे तुगे 20

1
@svidgen, बिना किसी अतिरिक्त प्रयास के इसे अमूर्त करने का एक और तरीका निर्भरता को उल्टा करना है - क्या समारोह उन पर कोई कार्रवाई करने के बजाय शहरों की एक सूची वापस कर सकता है (जैसे मूल कोड में "println")। यदि आवश्यक हो तो इसे और अधिक सारगर्भित किया जा सकता है, लेकिन बस यह एक परिवर्तन अपने आप में मूल प्रश्न में जोड़े गए आवश्यकताओं के लगभग आधे का ध्यान रखता है - और एक अशुद्ध फ़ंक्शन के बजाय जो सभी प्रकार के खराब सामान कर सकता है, आपके पास बस एक फ़ंक्शन है यह एक सूची देता है, और कॉलर खराब सामान करता है।
लुआं

2

गुणवत्ता, प्रयोज्यता, तकनीकी ऋण आदि के समान उत्तर:

आप के रूप में पुन: प्रयोज्य , उपयोगकर्ता, 1 उन्हें होने की जरूरत है

यह मूल रूप से एक निर्णय कॉल है - चाहे एब्सट्रैक्ट को डिजाइन करने और बनाए रखने की लागत को लागत (= समय और प्रयास) द्वारा वापस किया जाएगा, यह आपको लाइन से बचाएगा।

  • "डाउन द लाइन" वाक्यांश पर ध्यान दें: यहां पेऑफ मैकेनिक है, इसलिए यह इस बात पर निर्भर करेगा कि आप आगे इस कोड के साथ कितना काम करेंगे। उदाहरण के लिए:
    • क्या यह एक बार बंद होने वाली परियोजना है, या क्या यह लंबे समय से उत्तरोत्तर बेहतर होता जा रहा है?
    • क्या आप अपने डिजाइन में विश्वास रखते हैं, या आपको अगले प्रोजेक्ट / मील के पत्थर के लिए इसे अलग-अलग रूप से बदलना होगा या अन्यथा इसे बदलना होगा (जैसे किसी अन्य ढांचे को आज़माएं)?
  • अनुमानित लाभ भविष्य की भविष्यवाणी करने की आपकी क्षमता (ऐप में बदलाव) पर भी निर्भर करता है। कभी-कभी, आप उचित रूप से उस स्थान को देख सकते हैं जो आपका ऐप लेने जा रहा है। अधिक बार, आपको लगता है कि आप कर सकते हैं लेकिन आप वास्तव में नहीं कर सकते। यहाँ अंगूठे के नियम YAGNI सिद्धांत है और तीन का नियम है - दोनों ही आप जो जानते हैं, उस पर काम करने पर जोर देते हैं।

1 यह एक कोड निर्माण है, इसलिए आप इस मामले में "उपयोगकर्ता" हैं - स्रोत कोड का उपयोगकर्ता


1

एक स्पष्ट प्रक्रिया है जिसका आप अनुसरण कर सकते हैं:

  • एक एकल सुविधा के लिए एक असफल परीक्षा लिखें, जो अपने आप में एक "बात" है (यानी, एक सुविधा का कुछ मनमाना विभाजन नहीं है जहां न तो आधा वास्तव में समझ में आता है)।
  • हरे रंग को पास करने के लिए पूर्ण न्यूनतम कोड लिखें, एक पंक्ति अधिक नहीं।
  • धोये और दोहराएं।
  • (यदि आवश्यक हो तो रिफलेक्टर अथक रूप से, जो महान परीक्षण कवरेज के कारण आसान होना चाहिए।)

इसके साथ बदल जाता है - कम से कम कुछ लोगों की राय में - बहुत अधिक इष्टतम कोड, चूंकि यह जितना संभव हो उतना छोटा है, प्रत्येक समाप्त सुविधा में जितना संभव हो उतना कम समय लगता है (यदि आप पूर्ण रूप से देखें तो यह सच नहीं हो सकता है) उत्पाद रिफैक्टरिंग के बाद), और इसमें बहुत अच्छा परीक्षण कवरेज है। यह भी अधिक से अधिक इंजीनियर-सामान्य तरीकों या कक्षाओं से बचा जाता है।

यह आपको बहुत स्पष्ट निर्देश देता है कि चीजों को सामान्य बनाने के लिए और विशेषज्ञ कब करना है।

मुझे आपका शहर उदाहरण अजीब लगता है; मुझे बहुत संभावना है कि कभी भी शहर का नाम हार्डकोड नहीं होगा। यह इतना स्पष्ट है कि अतिरिक्त शहर बाद में शामिल किए जाएंगे, जो भी आप कर रहे हैं। लेकिन एक और उदाहरण रंग होगा। कुछ परिस्थितियों में, "लाल" या "ग्रीन" को हार्डकॉन्ड करना एक संभावना होगी। उदाहरण के लिए, ट्रैफ़िक लाइट एक ऐसा सर्वव्यापी रंग है, जिसे आप बस इससे दूर कर सकते हैं (और आप हमेशा रिफ्लेक्टर कर सकते हैं)। अंतर यह है कि "लाल" और "हरा" का सार्वभौमिक, "हार्डकोड" अर्थ है हमारी दुनिया में, यह अविश्वसनीय रूप से संभावना नहीं है कि यह कभी भी बदल जाएगा, और वास्तव में कोई विकल्प भी नहीं है।

आपकी पहली दिन की बचत विधि बस टूट गई है। हालांकि यह विशिष्टताओं के अनुरूप है, हार्डकॉन्ड 2018 विशेष रूप से खराब है क्योंकि a) यह तकनीकी "अनुबंध" (विधि नाम में, इस मामले में) में उल्लिखित नहीं है, और b) यह जल्द ही पुराना हो जाएगा, इसलिए ब्रेक्जिट गेट-गो से शामिल है। उन चीजों के लिए जो समय / तारीख से संबंधित हैं, यह शायद ही कभी एक विशिष्ट मूल्य को हार्डकोड करने के लिए समझ में आता है, ठीक है, समय आगे बढ़ता है। लेकिन इसके अलावा, बाकी सब चर्चा के लिए है। यदि आप इसे एक सरल वर्ष देते हैं और फिर हमेशा पूरे वर्ष की गणना करते हैं, तो आगे बढ़ें। आपके द्वारा सूचीबद्ध अधिकांश चीजें (स्वरूपण, एक छोटी श्रेणी की पसंद, आदि) चिल्लाती हैं कि आपकी विधि बहुत अधिक कर रही है, और इसके बजाय संभवतः मानों की एक सूची / सरणी वापस करना चाहिए ताकि कॉलर स्वयं को स्वरूपण / फ़िल्टर कर सके।

लेकिन दिन के अंत में, इस में से अधिकांश राय, स्वाद, अनुभव और व्यक्तिगत पूर्वाग्रह हैं, इसलिए इसके बारे में बहुत अधिक ध्यान न दें।


अपने दूसरे से अंतिम पैराग्राफ के बारे में - शुरू में दी गई "आवश्यकताओं" को देखें, अर्थात जो पहली विधि पर आधारित थी। यह 2018 को निर्दिष्ट करता है, इसलिए कोड तकनीकी रूप से सही है (और संभवतः आपके सुविधा-संचालित दृष्टिकोण से मेल खाएगा)।
dwizum

@dwizum, यह आवश्यकताओं के संबंध में सही है, लेकिन विधि नाम भ्रामक है। 2019 में, कोई भी प्रोग्रामर सिर्फ विधि के नाम को देखकर यह मान लेगा कि यह जो कुछ भी कर रहा है (शायद चालू वर्ष के लिए मान लौटाए), न कि 2018 ... मैं और अधिक स्पष्ट करने के लिए उत्तर में एक वाक्य जोड़ूंगा कि मेरा क्या मतलब है।
AnoE

1

मैं इस राय पर आया हूं कि पुन: प्रयोज्य कोड के दो प्रकार हैं:

  • कोड जो पुन: प्रयोज्य है क्योंकि यह एक ऐसी मौलिक, बुनियादी चीज है।
  • कोड जो पुन: प्रयोज्य है क्योंकि इसमें हर जगह के लिए पैरामीटर, ओवरराइड और हुक हैं।

पुन: प्रयोज्यता का पहला प्रकार अक्सर एक अच्छा विचार है। यह सूचियों, हैशमैप, की / वैल्यू स्टोर, स्ट्रिंग मैचर्स (जैसे रेगेक्स, ग्लोब, ...), ट्यूपल्स, यूनिफिकेशन, सर्च ट्री (गहराई-पहले, चौड़ाई-पहले, पुनरावृत्ति-गहनता, ...) जैसी चीजों पर लागू होता है। , पार्सर कॉम्बिनेटर, कैश / ज्ञापन, डेटा प्रारूप पाठक / लेखक (एस-एक्सप्रेशंस, एक्सएमएल, जेएसएन, प्रोटोबॉफ, ...), कार्य कतार, आदि।

ये चीजें बहुत सामान्य हैं, एक बहुत ही सार तरीके से, कि वे दिन-प्रतिदिन की प्रोग्रामिंग में सभी जगह फिर से उपयोग की जाती हैं। यदि आप स्वयं को विशेष-प्रयोजन कोड लिखते हुए पाते हैं जो अधिक सरल / सामान्य बना दिया जाता है (जैसे यदि हमारे पास "ग्राहक आदेशों की सूची" है, तो हम "ग्राहक सूची" सामान को "सूची" प्राप्त करने के लिए फेंक सकते हैं। ) तो इसे बाहर खींचने के लिए एक अच्छा विचार हो सकता है। यहां तक ​​कि अगर यह फिर से इस्तेमाल नहीं किया जाता है, तो यह हमें असंबंधित कार्यक्षमता को कम करने देता है।

दूसरा प्रकार वह है जहां हमारे पास कुछ ठोस कोड होते हैं, जो एक वास्तविक मुद्दे को हल करता है, लेकिन यह निर्णय का एक पूरा गुच्छा बनाकर करता है। हम उन निर्णयों को "सॉफ्ट-कोडिंग" द्वारा और अधिक सामान्य / पुन: प्रयोज्य बना सकते हैं, जैसे कि उन्हें मापदंडों में बदलना, कार्यान्वयन को जटिल बनाना और इससे भी अधिक ठोस विवरणों में बेकिंग करना (यानी ज्ञान जिसके हुक हम ओवरराइड के लिए चाहते हैं)। आपका उदाहरण इस प्रकार का है। इस तरह की पुन: प्रयोज्यता के साथ समस्या यह है कि हम अन्य लोगों या हमारे भावी स्वयं के उपयोग के मामलों पर अनुमान लगाने की कोशिश कर सकते हैं। आखिरकार हम इतने सारे मापदंडों को समाप्त कर सकते हैं कि हमारा कोड प्रयोग करने योग्य नहीं है, पुन: प्रयोज्य चलो! दूसरे शब्दों में, जब कॉलिंग होती है तो हमारे अपने संस्करण को लिखने की तुलना में अधिक प्रयास होता है। यह वह जगह है जहां YAGNI (यू ऐनोट गोना नीड इट) महत्वपूर्ण है। कई बार, "पुन: प्रयोज्य" कोड पर इस तरह के प्रयासों का पुन: उपयोग नहीं किया जाता है, क्योंकि यह उन उपयोग-मामलों के साथ असंगत हो सकता है जो मापदंडों की तुलना में अधिक मौलिक रूप से उपयोग कर सकते हैं, या वे संभावित उपयोगकर्ता अपने स्वयं के रोल करेंगे (बिल्ली, सभी को देखें) मानक और पुस्तकालय, जिनके लेखक "सरल" शब्द के साथ उपसर्ग करते हैं, उन्हें पूर्ववर्ती से अलग करने के लिए))।

"पुन: प्रयोज्यता" का यह दूसरा रूप मूल रूप से आवश्यक रूप से किया जाना चाहिए। ज़रूर, आप वहां कुछ "स्पष्ट" मापदंडों को चिपका सकते हैं, लेकिन भविष्य की भविष्यवाणी करने की कोशिश शुरू नहीं करते हैं। YAGNI।


क्या हम यह कह सकते हैं कि आप सहमत हैं कि मेरा पहला कदम ठीक था, जहां वर्ष भी हार्डकोड किया गया था? या यदि आप शुरू में उस आवश्यकता को लागू कर रहे थे, तो क्या आप अपने पहले लेने में वर्ष को एक पैरामीटर बना लेंगे?
कोरे तुगे

आपकी पहली टेक ठीक थी, क्योंकि आवश्यकता थी 'कुछ जांचने' की एकबारगी स्क्रिप्ट की। यह उसका 'नैतिक' परीक्षण विफल करता है, लेकिन वह 'कोई हठधर्मिता' परीक्षण में विफल रहता है। "वह कह सकता है ..." आवश्यकताओं की खोज कर रहा है आप की आवश्यकता नहीं है।
वॉर्बो

हम यह नहीं कह सकते कि अधिक जानकारी के बिना 'शहर को नष्ट करना' क्या "बेहतर" है: destroyBaghdadयह एक बार की स्क्रिप्ट है (या कम से कम, यह बेकार है)। हो सकता है कि किसी भी शहर को नष्ट करना एक सुधार हो, लेकिन क्या होगा अगर destroyBaghdadटिगरिस में बाढ़ आ जाए? यह मोसुल और बसरा के लिए पुन: प्रयोज्य हो सकता है, लेकिन मक्का या अटलांटा के लिए नहीं।
वारबो

मैं देख रहा हूँ तो आप उद्धरण के मालिक नथानिएल बोरेंस्टीन से असहमत हैं। मैं इन सभी प्रतिक्रियाओं और चर्चाओं को पढ़कर धीरे-धीरे सोचने की कोशिश कर रहा हूं।
कोरे तुगे

1
मुझे यह भेदभाव पसंद है। यह हमेशा स्पष्ट नहीं होता है, और हमेशा "सीमा मामले" होते हैं। लेकिन सामान्य तौर पर, मैं "बिल्डिंग ब्लॉक्स" (अक्सर staticतरीकों के रूप में ) का एक प्रशंसक हूं, जो विशुद्ध रूप से कार्यात्मक और निम्न-स्तर के हैं, और इसके विपरीत, "कॉन्फ़िगर करने वाले मापदंडों और हुक" के बारे में निर्णय लेना आमतौर पर है जहां आपको कुछ संरचनाओं का निर्माण करना होगा जो उचित होने के लिए कहें।
मार्को 13

1

पहले से ही कई उत्कृष्ट और विस्तृत उत्तर हैं। उनमें से कुछ विशिष्ट विवरणों में गहराई से जाते हैं, सामान्य रूप से सॉफ्टवेयर विकास के तरीकों पर कुछ दृष्टिकोण निर्धारित करते हैं, और उनमें से कुछ में निश्चित रूप से विवादास्पद तत्व या "राय" छिड़का हुआ है।

Warbo द्वारा जवाब पहले से ही अलग-अलग बताया प्रकार पुनर्प्रयोग की। अर्थात्, क्या कुछ पुन: प्रयोज्य है क्योंकि यह एक मौलिक निर्माण खंड है, या क्या कुछ पुन: प्रयोज्य है क्योंकि यह किसी तरह से "सामान्य" है। उत्तरार्द्ध का उल्लेख करते हुए, कुछ ऐसा है जिसे मैं पुन: प्रयोज्य के लिए किसी प्रकार के उपाय के रूप में मानूंगा:

एक विधि दूसरे का अनुकरण कर सकती है या नहीं ।

प्रश्न से उदाहरण के बारे में: कल्पना करें कि विधि

void dayLightSavings()

एक ग्राहक द्वारा अनुरोध की गई कार्यक्षमता का कार्यान्वयन था। तो यह कुछ ऐसा होगा जिसे अन्य प्रोग्रामर उपयोग करने वाले हैं , और इस प्रकार, एक सार्वजनिक तरीका है, जैसे कि

publicvoid dayLightSavings()

इसे लागू किया जा सकता है जैसा आपने अपने उत्तर में दिखाया था। अब, कोई इसे वर्ष के साथ पैरामीटर बनाना चाहता है। तो आप एक विधि जोड़ सकते हैं

publicvoid dayLightSavings(int year)

और मूल कार्यान्वयन को सिर्फ होने के लिए बदलें

public void dayLightSavings() {
    dayLightSavings(2018);
}

अगले "सुविधा अनुरोध" और सामान्यीकरण एक ही पैटर्न का पालन करते हैं। इसलिए यदि और केवल अगर सबसे सामान्य रूप की मांग है, तो आप इसे लागू कर सकते हैं, यह जानकर कि यह सबसे सामान्य रूप अधिक विशिष्ट लोगों के तुच्छ कार्यान्वयन के लिए अनुमति देता है:

public void dayLightSavings() {
    dayLightSavings(2018, 0, 12, 0, 12, new DateTimeFormatter(...));
}

यदि आपने भविष्य के एक्सटेंशन और फ़ीचर अनुरोधों का अनुमान लगाया था, और आपके निपटान में कुछ समय था और (संभवतः बेकार) सामान्यीकरण के साथ एक उबाऊ सप्ताहांत बिताना चाहते थे, तो आप शुरुआत से ही सबसे सामान्य एक के साथ शुरू कर सकते थे । लेकिन केवल एक निजी पद्धति के रूप में। जब तक आप केवल उस सरल विधि को उजागर करते हैं जो ग्राहक द्वारा सार्वजनिक विधि के रूप में अनुरोध किया गया था , आप सुरक्षित हैं।

टीएल; डीआर :

सवाल वास्तव में इतना नहीं है "एक विधि कैसे पुन: प्रयोज्य होनी चाहिए"। सवाल यह है कि इस पुन: प्रयोज्य का कितना विस्तार होता है, और एपीआई कैसा दिखता है। एक विश्वसनीय एपीआई बनाना जो समय की कसौटी पर खरा उतर सके (यहां तक ​​कि जब आगे की आवश्यकताएं बाद में सामने आती हैं) एक कला और एक शिल्प है, और यहां इसे कवर करने के लिए विषय बहुत जटिल है। एक प्रस्तुति के लिए यहोशू बलोच या एपीआई डिजाइन बुक विकी की इस प्रस्तुति पर एक नज़र डालें ।


dayLightSavings()कॉलिंग dayLightSavings(2018)मुझे एक अच्छा विचार नहीं लगता है।
कोरा तुगे

@KorayTugay जब शुरुआती अनुरोध यह है कि इसे "2018 के लिए दिन की बचत" प्रिंट करना चाहिए, तो यह ठीक है। वास्तव में, यह है कि वास्तव में विधि है कि आप मूल रूप से लागू किया। अगर यह " वर्तमान वर्ष के लिए दिन के उजाले की बचत को प्रिंट करना चाहिए , तो निश्चित रूप से आप फोन करेंगे dayLightSavings(computeCurrentYear());...
मार्को 13

0

अंगूठे का एक अच्छा नियम है: आपकी विधि पुन: प्रयोज्य ... पुन: प्रयोज्य होनी चाहिए।

यदि आप उम्मीद करते हैं कि आप अपने तरीके को केवल एक ही स्थान पर कहेंगे, तो इसमें केवल ऐसे पैरामीटर होने चाहिए जो कॉल साइट के लिए जाने जाते हैं और जो इस पद्धति के लिए उपलब्ध नहीं हैं।

यदि आपके पास अधिक कॉलर्स हैं, तो आप नए पैरामीटर पेश कर सकते हैं जब तक कि अन्य कॉलर्स उन मापदंडों को पारित कर सकते हैं; अन्यथा आपको नई विधि की आवश्यकता है।

समय के साथ कॉल करने वालों की संख्या बढ़ सकती है, आपको रिफैक्टिंग या ओवरलोडिंग के लिए तैयार रहने की आवश्यकता है। कई मामलों में इसका मतलब है कि आपको अभिव्यक्ति का चयन करने के लिए सुरक्षित महसूस करना चाहिए और अपने आईडीई की "एक्सट्रैक्ट पैरामीटर" कार्रवाई को चलाना चाहिए।


0

अति संक्षिप्त उत्तर: आपके सामान्य मॉड्यूल के अन्य कोड के लिए कम युग्मन या निर्भरता जितना अधिक पुन: प्रयोज्य हो सकता है।

आपका उदाहरण केवल पर निर्भर करता है

import java.time.*;
import java.util.Set;

इसलिए सिद्धांत रूप में यह अत्यधिक पुन: प्रयोज्य हो सकता है।

व्यवहार में, मुझे नहीं लगता है कि आपके पास कभी भी दूसरा उपयोगकत्र्ता होगा, जिसे इस कोड की आवश्यकता है, इसलिए निम्नलिखित याग्नी सिद्धांत के बाद मैं इसे पुन: प्रयोज्य नहीं बनाऊंगा यदि 3 से अधिक विभिन्न प्रोजेट नहीं हैं जिन्हें इस कोड की आवश्यकता है।

पुन: प्रयोज्य के अन्य पहलुओं का उपयोग में आसानी होती है और डॉक्यूमेंटेशन जो टेस्ट ड्रिवेन डिवेलपमेंट के साथ होते हैं : यदि आपके पास एक साधारण यूनिट-टेस्ट है जो आपके सामान्य उपयोगकर्ताओं के लिए कोडिंग उदाहरण के रूप में आपके जेनेरिक मॉड्यूल के आसान उपयोग को प्रदर्शित करता है।


0

यह मेरे द्वारा हाल ही में गढ़ा गया एक नियम बताने का एक अच्छा अवसर है:

एक अच्छा प्रोग्रामर होने का मतलब है भविष्य का अनुमान लगाना।

बेशक, यह कड़ाई से असंभव है! सब के बाद, आप कभी नहीं के लिए पता सुनिश्चित करें कि आप प्रदर्शन करने के लिए, क्या नई सुविधाओं अपने उपयोगकर्ताओं चाहता हूँ चाहता हूँ जो संबंधित कार्यों क्या सामान्यीकरण आप बाद में उपयोगी मानते हैं,, और सी। लेकिन अनुभव कभी-कभी आपको एक कठिन विचार देता है जो काम में आ सकता है।

आपको जिन अन्य कारकों को संतुलित करना है, वे हैं कि कितना अतिरिक्त समय और प्रयास शामिल होगा, और यह आपके कोड को कितना अधिक जटिल बना देगा। कभी-कभी आप भाग्यशाली होते हैं, और अधिक सामान्य समस्या को हल करना वास्तव में सरल होता है! (कम से कम वैचारिक रूप से, यदि कोड की मात्रा में नहीं है।) लेकिन अधिक बार, एक जटिलता लागत के साथ-साथ समय और प्रयास में से एक है।

इसलिए यदि आपको लगता है कि एक सामान्यीकरण की आवश्यकता होने की बहुत संभावना है, तो यह अक्सर करने योग्य है (जब तक कि यह बहुत काम या जटिलता को जोड़ता नहीं है ); लेकिन अगर इसकी संभावना बहुत कम लगती है, तो यह शायद नहीं है (जब तक कि यह बहुत आसान और / या कोड को सरल नहीं करता है)।

(हाल के उदाहरण के लिए: पिछले हफ्ते मुझे एक युक्ति दी गई थी। क्रियाओं के लिए एक सिस्टम को कुछ समय समाप्त होने के ठीक 2 दिन बाद होना चाहिए। इसलिए निश्चित रूप से मैंने 2-दिन की अवधि को एक पैरामीटर बना दिया। इस सप्ताह व्यवसाय के लोग खुश थे, क्योंकि वे। उस एन्हांसमेंट के बारे में पूछने वाले थे! मैं भाग्यशाली था: यह एक आसान बदलाव था, और मैंने अनुमान लगाया कि यह वांछित होने की काफी संभावना है। अक्सर यह न्याय करना कठिन होता है। लेकिन यह अभी भी भविष्यवाणी करने के लिए लायक है, और अनुभव अक्सर एक अच्छा अनुभव होता है। ।)


0

सबसे पहले, 'मुझे कैसे पता चलेगा कि मेरे तरीकों को कैसे पुन: प्रयोज्य होना चाहिए? "का सबसे अच्छा उत्तर है।" अनुभव "। इसे कुछ हज़ार बार करें, और आप आमतौर पर सही उत्तर प्राप्त करते हैं। लेकिन एक टीज़र के रूप में, मैं आपको अंतिम दे सकता हूं। इस उत्तर की पंक्ति: आपका ग्राहक आपको बताएगा कि आपको कितना लचीलापन और सामान्यीकरण की कितनी परतें चाहिए।

इनमें से कई उत्तरों में सलाह के विशिष्ट टुकड़े हैं। मैं कुछ अधिक सामान्य देना चाहता था ... क्योंकि विडंबना यह है कि बहुत मज़ा आता है!

जैसा कि कुछ उत्तरों ने उल्लेख किया है, सामान्यता महंगी है। हालाँकि, यह वास्तव में नहीं है। हर बार नहीं। व्यय को समझना पुन: प्रयोज्य खेल खेलने के लिए आवश्यक है।

मैं चीजों को "अपरिवर्तनीय" से "प्रतिवर्ती" के पैमाने पर रखने पर ध्यान केंद्रित करता हूं। यह एक सहज पैमाना है। केवल सही मायने में अपरिवर्तनीय बात है "परियोजना पर खर्च किया गया समय।" आपको वे संसाधन कभी वापस नहीं मिलेंगे। थोड़ा कम प्रतिवर्ती "गोल्डन एपीआई" जैसी परिस्थितियां हो सकती हैं जैसे कि विंडोज एपीआई। उस एपीआई में दशकों से डिप्रेस्ड फीचर्स बने हुए हैं क्योंकि माइक्रोसॉफ्ट का बिजनेस मॉडल इसके लिए कहता है। यदि आपके पास ऐसे ग्राहक हैं जिनके संबंध कुछ API सुविधा को पूर्ववत करने से स्थायी रूप से क्षतिग्रस्त हो जाएंगे, तो उसे अपरिवर्तनीय माना जाना चाहिए। पैमाने के दूसरे छोर को देखते हुए, आपके पास प्रोटोटाइप कोड जैसी चीजें हैं। यदि आपको यह पसंद नहीं है कि यह कहाँ जाता है, तो आप बस इसे फेंक सकते हैं। थोड़ा कम प्रतिवर्ती आंतरिक उपयोग एपीआई हो सकता है। वे एक ग्राहक को परेशान किए बिना, फिर से बनाए जा सकते हैं,समय (सभी का सबसे अपरिवर्तनीय संसाधन!)

इसलिए इन्हें एक पैमाने पर रखें। अब आप एक हेयुरिस्टिक लागू कर सकते हैं: जितना अधिक प्रतिवर्ती कुछ होगा, उतना ही आप इसे भविष्य की गतिविधियों के लिए उपयोग कर सकते हैं। यदि कुछ अपरिवर्तनीय है, तो इसका उपयोग केवल ठोस ग्राहक-चालित कार्यों के लिए करें। यही कारण है कि आप चरम प्रोग्रामिंग से उन सिद्धांतों को देखते हैं जो केवल वही करने का सुझाव देते हैं जो ग्राहक पूछता है और अधिक कुछ नहीं। ये सिद्धांत यह सुनिश्चित करने में अच्छे हैं कि आप कुछ ऐसा नहीं करते जिसके लिए आपको खेद है।

DRY सिद्धांत जैसी चीजें उस संतुलन को स्थानांतरित करने का एक तरीका सुझाती हैं। यदि आप स्वयं को दोहराते हुए पाते हैं, तो यह मूल रूप से एक आंतरिक एपीआई बनाने का अवसर है। कोई भी ग्राहक इसे नहीं देखता है, इसलिए आप इसे हमेशा बदल सकते हैं। एक बार जब आपके पास यह आंतरिक एपीआई है, तो अब आप आगे की चीजों को देखना शुरू कर सकते हैं। आपको लगता है कि आपकी पत्नी आपको कितने समय के लिए अलग-अलग समय पर आधारित कार्य देती है? क्या आपके पास कोई अन्य ग्राहक है जो टाइमज़ोन आधारित कार्य करना चाहता है? यहां आपके लचीलेपन को आपके वर्तमान ग्राहकों की ठोस मांगों द्वारा खरीदा जाता है, और यह भविष्य के ग्राहकों की संभावित मांगों का समर्थन करता है।

यह स्तरित सोच दृष्टिकोण है, जो स्वाभाविक रूप से DRY से स्वाभाविक रूप से आता है जो आपको बिना कचरे के सामान्यीकरण प्रदान करता है। लेकिन क्या इसकी कोई सीमा है? जरूर है। लेकिन इसे देखने के लिए, आपको पेड़ों के लिए जंगल देखना होगा।

यदि आपके पास flexiblity की कई परतें हैं, तो वे अक्सर उन परतों के प्रत्यक्ष नियंत्रण की कमी का कारण बनते हैं जो आपके ग्राहकों का सामना करते हैं। मेरे पास सॉफ्टवेयर है जहां मैंने एक ग्राहक को यह समझाने का क्रूर काम किया है कि वे 10 परतों में बने लचीलेपन के कारण ऐसा क्यों नहीं कर सकते जो वे चाहते थे, जिसे वे कभी नहीं देखना चाहते थे। हमने खुद को एक कोने में लिखा। हमने अपने आप को उन सभी लचीलेपन के साथ एक गाँठ में बाँध लिया जिन्हें हमने सोचा था कि हमें ज़रूरत है।

इसलिए जब आप यह सामान्यीकरण / DRY ट्रिक कर रहे हों, तो हमेशा अपने ग्राहक पर एक पल्स रखें । आपको क्या लगता है कि आपकी पत्नी आगे क्या मांगने वाली है? क्या आप खुद को उन जरूरतों को पूरा करने की स्थिति में ला रहे हैं? यदि आपके पास नैक है, तो ग्राहक आपको अपनी भविष्य की जरूरतों को प्रभावी रूप से बताएगा। यदि आपके पास नीक नहीं है, तो ठीक है, हम में से ज्यादातर सिर्फ अनुमान पर भरोसा करते हैं! (विशेष रूप से जीवनसाथी के साथ!) कुछ ग्राहक महान लचीलापन चाहते हैं, और आप इन सभी परतों के साथ विकसित होने वाली अतिरिक्त लागत को स्वीकार करने के लिए तैयार रहेंगे क्योंकि वे सीधे उन परतों के लचीलेपन से लाभान्वित होते हैं। अन्य ग्राहकों ने बल्कि अटूट आवश्यकताओं को निर्धारित किया है, और वे विकास को अधिक प्रत्यक्ष होना पसंद करते हैं। आपका ग्राहक आपको बताएगा कि आपको कितना लचीलापन और सामान्यीकरण की कितनी परतें चाहिए।


वैसे अन्य लोगों को भी होना चाहिए जिन्होंने 10000 बार ऐसा किया है, इसलिए मुझे 10000 बार क्यों करना चाहिए और जब मैं दूसरों से सीख सकता हूं तो अनुभव प्राप्त करना चाहिए? क्योंकि उत्तर प्रत्येक व्यक्ति के लिए अलग-अलग होगा, इसलिए अनुभवी से उत्तर मेरे लिए लागू नहीं हैं? यह भी Your customer will tell you how much flexibility and how many layers of generalization you should seek.क्या दुनिया है?
कोरे तुगे

@KorayTugay यह एक व्यवसायिक दुनिया है। यदि आपके ग्राहक आपको यह नहीं बता रहे हैं कि आपको क्या करना है, तो आप काफी मुश्किल नहीं सुन रहे हैं। बेशक, वे हमेशा आपको शब्दों में नहीं बताते हैं, लेकिन वे आपको अन्य तरीकों से बताते हैं। अनुभव आपको उनके अधिक सूक्ष्म संदेशों को सुनने में मदद करता है। यदि आपके पास अभी तक कौशल नहीं है, तो अपनी कंपनी में किसी ऐसे व्यक्ति को खोजें, जिसके पास उन सूक्ष्म ग्राहक संकेतों को सुनने का कौशल है, और उन्हें दिशा के लिए प्लाई करें। किसी के पास यह कौशल होगा, भले ही वे सीईओ हों या मार्केटिंग में।
Cort Ammon

आपके विशिष्ट मामले में, यदि आप कूड़े को बाहर निकालने में विफल रहे हैं क्योंकि आप विशिष्ट समाधान को एक साथ हैक करने के बजाय इस टाइमज़ोन समस्या के सामान्यीकृत संस्करण को कोड करने में व्यस्त थे, तो आपका ग्राहक कैसा महसूस करेगा?
कॉर्ट अमोन

तो आप सहमत हैं कि मेरा पहला दृष्टिकोण सही था, हार्डकॉडिंग 2018 पहले वर्ष के पैरामीटर के बजाय पहले ले? (btw, कि वास्तव में मेरे ग्राहक को नहीं सुन रहा है मुझे लगता है, कचरा उदाहरण। वह आपके ग्राहक को जान रहा है .. भले ही द ओरेकल से समर्थन प्राप्त हो, लेकिन जब वह कहता है कि मुझे दिन के उजाले की सूची की जरूरत है, तो सुनने के लिए कोई सूक्ष्म संदेश नहीं हैं। 2018 के लिए परिवर्तन।) अपने समय और उत्तर btw के लिए धन्यवाद।
कोरे तुगे

@KorayTugay बिना किसी अतिरिक्त विवरण को जाने, मैं कहूंगा कि हार्डकोडिंग सही दृष्टिकोण था। आपको यह जानने का कोई तरीका नहीं था कि आपको भविष्य के डीएलएस कोड की आवश्यकता है, और न ही यह पता है कि वह आगे किस तरह का अनुरोध दे सकता है। और यदि आपका ग्राहक आपकी परीक्षा लेने की कोशिश कर रहा है, तो उन्हें
Cort Ammon

0

कोई भी नैतिक रूप से प्रशिक्षित सॉफ्टवेयर इंजीनियर कभी भी एक विनाशबगड़ प्रक्रिया लिखने के लिए सहमति नहीं देगा। इसके बजाय बुनियादी पेशेवर नैतिकता को उसे एक विध्वंस प्रक्रिया लिखने की आवश्यकता होगी, जिसमें बगदाद को एक पैरामीटर के रूप में दिया जा सकता है।

यह उन्नत सॉफ़्टवेयर इंजीनियरिंग सर्कल में "मजाक" के रूप में जाना जाता है। चुटकुले वह नहीं है जिसे हम "सच" कहते हैं, हालांकि मज़ेदार होने के लिए उन्हें आम तौर पर कुछ सच में संकेत देना चाहिए।

इस विशेष मामले में, "मजाक" "सच" नहीं है। किसी भी शहर को नष्ट करने के लिए एक सामान्य प्रक्रिया लिखने में शामिल काम है, हम सुरक्षित रूप से मान सकते हैं, एक विशिष्ट को नष्ट करने के लिए आवश्यकता से अधिक परिमाण के आदेशFaridabad। अन्यथा, कोई भी व्यक्ति जिसने एक या मुट्ठी भर शहरों (बाइबिल जोशुआ, को नष्ट कर दिया, हम कहेंगे, या राष्ट्रपति ट्रूमैन) ने तुच्छ रूप से सामान्य किया कि वे क्या कर सकते थे और किसी भी शहर को नष्ट करने में सक्षम होंगे। तथ्य की बात में ऐसा नहीं है। उन विधियों को जो दो लोग प्रसिद्ध रूप से विशिष्ट शहरों को नष्ट करने के लिए उपयोग करते थे, जरूरी नहीं कि किसी भी समय किसी भी शहर पर काम करें। एक और शहर जिसकी दीवारों में अलग-अलग गुंजयमान आवृत्ति थी या जिनकी उच्च-ऊंचाई वाली हवाई सुरक्षा बेहतर थी, उन्हें दृष्टिकोण के मामूली या मूलभूत परिवर्तनों (एक अलग-अलग तरह की तुरही या एक रॉकेट) की आवश्यकता होगी।

यह समय के साथ परिवर्तनों के खिलाफ कोड रखरखाव की ओर भी जाता है: अब बहुत सारे शहर हैं जो आधुनिक निर्माण विधियों और सर्वव्यापी रडार की बदौलत न तो उन दृष्टिकोणों के लिए गिरेंगे।

पूरी तरह से सामान्य विकसित करने और परीक्षण करने का मतलब है कि किसी भी शहर को नष्ट कर देगा , इससे पहले कि आप सिर्फ एक शहर को नष्ट करने के लिए सहमत हों , एक सख्त अक्षम दृष्टिकोण है। कोई भी नैतिक रूप से प्रशिक्षित सॉफ्टवेयर इंजीनियर किसी समस्या को सामान्य करने की कोशिश नहीं करेगा, ताकि उसके नियोक्ता / ग्राहक की तुलना में अधिक काम करने के आदेशों की आवश्यकता हो, प्रदर्शन की आवश्यकता के बिना वास्तव में भुगतान करने की आवश्यकता हो।

तो क्या सच है? कभी-कभी सामान्यता को जोड़ना तुच्छ होता है। क्या ऐसा करने के लिए तुच्छ होने पर हमें हमेशा सामान्यता जोड़ना चाहिए? मैं अभी भी "नहीं, हमेशा नहीं" का तर्क दूंगा, क्योंकि लंबी अवधि के रखरखाव के मुद्दे के कारण। यह मानते हुए कि लेखन के समय, सभी शहर मूल रूप से एक जैसे होते हैं, इसलिए मैं नष्टता के साथ आगे बढ़ता हूं। एक बार जब मैंने यह लिखा है, एकीकरण परीक्षणों के साथ कि (इनपुट्स की सूक्ष्म रूप से अनगिनत जगह के कारण) हर ज्ञात शहर पर पुनरावृति करता है और यह सुनिश्चित करता है कि फ़ंक्शन प्रत्येक पर काम करता है (यह सुनिश्चित नहीं है कि यह कैसे काम करता है। संभवतः City.clone () कहते हैं। क्लोन को नष्ट कर देता है? वैसे भी)।

व्यवहार में बगदाद को नष्ट करने के लिए पूरी तरह से फ़ंक्शन का उपयोग किया जाता है, मान लीजिए कि कोई व्यक्ति एक नया शहर बनाता है जो मेरी तकनीकों के लिए प्रतिरोधी है (यह गहरी भूमिगत या कुछ और है)। अब मेरे पास एक उपयोग-मामले के लिए एक एकीकरण परीक्षण विफलता है जो वास्तव में मौजूद नहीं है , और इससे पहले कि मैं इराक के निर्दोष नागरिकों के खिलाफ आतंक के अपने अभियान को जारी रख सकूं, मुझे यह पता लगाना होगा कि सबटरेनिया को कैसे नष्ट किया जाए। कभी यह मत सोचिए कि यह नैतिक है या नहीं, यह गूंगा है और मेरे समय की बर्बादी है

तो, क्या आप वास्तव में एक फ़ंक्शन चाहते हैं जो किसी भी वर्ष के लिए दिन के उजाले की बचत का उत्पादन कर सकता है, सिर्फ 2018 के लिए डेटा का उत्पादन करने के लिए? हो सकता है, लेकिन यह निश्चित रूप से एक साथ परीक्षण के मामलों को डालने के लिए थोड़े से अतिरिक्त प्रयास की आवश्यकता है। यह वास्तव में आपके पास एक बेहतर समयक्षेत्र डेटाबेस प्राप्त करने के लिए बड़ी मात्रा में प्रयास की आवश्यकता हो सकती है। इसलिए उदाहरण के लिए, 1908 में, पोर्ट आर्थर, ओंटारियो के शहर में 1 जुलाई को डीएसटी शुरू होने की अवधि थी। क्या यह आपके OS के टाइमज़ोन डेटाबेस में है? नहीं सोचा, इसलिए आपका सामान्यीकृत कार्य गलत है । कोड लिखने के बारे में विशेष रूप से नैतिक कुछ भी नहीं है जो वादे करता है वह इसे नहीं रख सकता है।

ठीक है, इसलिए, उपयुक्त कैविटीज़ के साथ, यह एक फ़ंक्शन लिखना आसान है जो कि कई वर्षों तक टाइमज़ोन करता है, 1970-वर्तमान दिन कहते हैं। लेकिन यह उस फ़ंक्शन को लेना जितना आसान है, जो आपने वास्तव में लिखा था, और इसे वर्ष को व्यवस्थित करने के लिए सामान्यीकृत करें। तो यह वास्तव में अब सामान्य करने के लिए कोई और अधिक नैतिक / समझदार नहीं है, कि यह वही करना है जो आपने किया और फिर जरूरत पड़ने पर सामान्यीकरण करें।

हालाँकि, यदि आप जानते हैं कि आपकी पत्नी इस डीएसटी सूची की जांच क्यों करना चाहती है, तो आपको इस बारे में सूचित राय होगी कि क्या वह 2019 में फिर से वही सवाल पूछ सकती है और यदि हां, तो क्या आप खुद को उस पाश से बाहर ले जा सकते हैं उसे एक फ़ंक्शन जिसे वह कॉल कर सकती है, बिना उसे पुन: स्थापित करने की आवश्यकता के। एक बार जब आप उस विश्लेषण को कर लेते हैं, तो प्रश्न का उत्तर "यह हाल के वर्षों के लिए सामान्य होना चाहिए" "हां" हो सकता है। लेकिन आप अपने लिए एक और समस्या पैदा करते हैं, वह यह है कि भविष्य में समयक्षेत्र डेटा केवल अनंतिम है, और इसलिए यदि वह आज 2019 के लिए इसे चलाता है, वह महसूस कर सकती है या नहीं कर सकती है कि यह उसे सबसे अच्छा अनुमान लगा रहा है। इसलिए आपको अभी भी दस्तावेज़ों का एक गुच्छा लिखना होगा जो कम सामान्य फ़ंक्शन के लिए आवश्यक नहीं होगा ("डेटा टाइमज़ोन डेटाबेस ब्ला ब्ला से आता है यहां अपडेट ब्लाह ब्लाह पर उनकी नीतियों को देखने के लिए लिंक है")। यदि आप विशेष मामले से इनकार करते हैं, तो हर समय आप जो कर रहे हैं, वह उस कार्य के साथ नहीं हो सकता है जिसके लिए उसे 2018 डेटा की आवश्यकता थी, क्योंकि 2019 के बारे में कुछ बकवास के बारे में वह अभी तक परवाह नहीं करता है।

मुश्किल चीजों को बिना ठीक से सोचे समझे न करें, सिर्फ इसलिए कि एक चुटकुला आपको सुनाए। क्या यह उपयोगी है? क्या यह उस उपयोगिता की डिग्री के लिए काफी सस्ता है?


0

यह आकर्षित करने के लिए एक आसान रेखा है क्योंकि वास्तुकला के अंतरिक्ष यात्रियों द्वारा परिभाषित पुन: प्रयोज्य है।

एप्लिकेशन डेवलपर्स द्वारा बनाए गए लगभग सभी कोड बेहद डोमेन विशिष्ट हैं। यह 1980 नहीं है। लगभग सब कुछ परेशान करने लायक है जो पहले से ही एक ढांचे में है।

अंश और परंपराओं के लिए दस्तावेज़ीकरण और सीखने के प्रयास की आवश्यकता होती है। कृपया इसके लिए नए लोगों को बनाना बंद करें। (मैं पर देख रहा हूँ तुम , जावास्क्रिप्ट लोग!)

चलिए उस अमूर्त फंतासी को लिप्त करते हैं जिसे आपने कुछ ऐसा पाया है जो वास्तव में आपकी पसंद के ढांचे में होना चाहिए। आप जिस तरह से आम तौर पर करते हैं आप कोड को धमाका नहीं कर सकते। अरे नहीं, आपको न केवल इच्छित उपयोग के लिए बल्कि सभी ज्ञात किनारे के मामलों के लिए, सभी कल्पनीय असफलता मोड के लिए, निदान के लिए परीक्षण मामलों, परीक्षण डेटा, तकनीकी दस्तावेज, उपयोगकर्ता प्रलेखन, रिलीज प्रबंधन, समर्थन के लिए परीक्षण कवरेज की आवश्यकता है स्क्रिप्ट, प्रतिगमन परीक्षण, परिवर्तन प्रबंधन ...

क्या आपका नियोक्ता सभी के लिए भुगतान करने में प्रसन्न है? मैं नहीं कहने जा रहा हूँ।

अमूर्तता वह मूल्य है जो हम लचीलेपन के लिए भुगतान करते हैं। यह हमारे कोड को अधिक जटिल और समझने में कठिन बनाता है। जब तक लचीलापन एक वास्तविक और वर्तमान आवश्यकता को पूरा नहीं करता है, तब तक नहीं, क्योंकि YAGNI।

आइए एक वास्तविक विश्व उदाहरण पर ध्यान दें, जिसका मुझे अभी सामना करना था: HTMLRenderer। जब मैं एक प्रिंटर के डिवाइस संदर्भ को प्रस्तुत करने की कोशिश करता था तो यह ठीक से स्केलिंग नहीं करता था। मुझे पूरे दिन यह पता चला कि डिफ़ॉल्ट रूप से यह GDI (जिसका कोई पैमाना नहीं है) का उपयोग GDI + (जो नहीं करता है, लेकिन एंटीलिया नहीं करता) के कारण किया गया था क्योंकि मुझे मिलने से पहले दो विधानसभाओं में अप्रत्यक्षता के छह स्तरों से गुजरना पड़ा था कोड जो कुछ भी किया

इस मामले में मैं लेखक को क्षमा करूँगा। अमूर्त वास्तव में है आवश्यक है क्योंकि इस है WinForms, WPF, डॉटनैट कोर, मोनो और PdfSharp: ढांचे कोड कि पांच बहुत अलग प्रतिपादन लक्ष्य निशाना बनाता है।

लेकिन यह केवल मेरी बात को रेखांकित करता है: आप निश्चित रूप से कुछ बेहद जटिल नहीं कर रहे हैं (स्टाइलशीट के साथ HTML रेंडरिंग) सभी प्लेटफार्मों पर उच्च प्रदर्शन के एक घोषित लक्ष्य के साथ कई प्लेटफार्मों को लक्षित कर रहे हैं।

आपका कोड लगभग निश्चित रूप से व्यावसायिक नियमों के साथ एक और डेटाबेस ग्रिड है जो केवल आपके नियोक्ता और कर नियमों पर लागू होता है जो केवल आपके राज्य में लागू होता है, एक ऐसे अनुप्रयोग में जो बिक्री के लिए नहीं है।

वह सब जो अप्रत्यक्ष रूप से आपके पास एक समस्या है और आपके कोड को पढ़ने के लिए बहुत कठिन बना देता है , जो रखरखाव की लागत को बड़े पैमाने पर बढ़ाता है और आपके नियोक्ता के लिए बहुत बड़ा असंतोष है। सौभाग्य से जो लोग इस बारे में शिकायत करना चाहते थे वे समझ नहीं पा रहे हैं कि आप उनके साथ क्या कर रहे हैं।

एक प्रतिवाद यह है कि इस तरह का अमूर्त परीक्षण संचालित विकास का समर्थन करता है, लेकिन मुझे लगता है कि टीडब्लूडी बिलॉक भी है, क्योंकि यह मानता है कि व्यवसाय को अपनी आवश्यकताओं की स्पष्ट, पूर्ण और सही समझ है। TDD नासा के लिए महान है और चिकित्सा उपकरणों और सेल्फ-ड्राइविंग कारों के लिए नियंत्रण सॉफ्टवेयर, लेकिन बाकी सभी के लिए बहुत महंगा है।


संयोग से, यह भविष्यवाणी करना संभव नहीं है सब दुनिया में डेलाइट बचत। विशेष रूप से इज़राइल में हर साल लगभग 40 संक्रमण होते हैं जो सभी जगह आशा करते हैं क्योंकि हमारे पास गलत समय पर प्रार्थना करने वाले लोग नहीं हो सकते हैं और भगवान दिन के उजाले की बचत नहीं करते हैं।


यद्यपि मैं सार और सीखने के प्रयास के बारे में आपके द्वारा कही गई बातों से सहमत हूं, और विशेष रूप से जब इसे "जावास्क्रिप्ट" कहा जाता है, तो मैं दृढ़ता से पहले वाक्य से असहमत हूं। पुन: प्रयोज्य कई स्तरों पर हो सकता है, यह बहुत दूर तक चला जा सकता है , और थ्रो-दूर कोड को फेंक-दूर प्रोग्रामर द्वारा लिखा जा सकता है। लेकिन वहाँ रहे हैं लोग हैं, जो कम से कम करने के लिए पर्याप्त आदर्शवादी हैं उद्देश्य पुन: प्रयोज्य कोड पर। आपके लिए एक दया की बात है अगर आपको इसके लाभ नहीं दिखते हैं।
मार्को 13

@ Marco13 - चूँकि आपकी आपत्ति वाजिब है इसलिए मैं इस बात का विस्तार करूँगा।
पीटर वॉन

-3

यदि आप कम से कम जावा 8 का उपयोग कर रहे हैं, तो आप वर्ल्डटाइमज़ोन क्लास को लिखेंगे कि यह प्रदान करने के लिए कि क्या सार समय क्षेत्रों का संग्रह प्रतीत होता है।

फिर WorldTimeZones वर्ग के लिए एक फ़िल्टर (Predicate फ़िल्टर) विधि जोड़ें। यह कॉल करने वाले के लिए पैरामीटर के रूप में एक लैम्ब्डा एक्सप्रेशन पास करके किसी भी चीज़ को फ़िल्टर करने की क्षमता प्रदान करता है।

संक्षेप में, एकल फ़िल्टर विधि विधेय के लिए पारित मूल्य में निहित किसी भी चीज़ पर फ़िल्टरिंग का समर्थन करती है।

वैकल्पिक रूप से, अपने WorldTimeZones वर्ग में एक धारा () विधि जोड़ें जो कि समय क्षेत्र की एक धारा पैदा करता है जिसे कहा जाता है। फिर कॉल करने वाला, फ़िल्टर कर सकता है, मैप कर सकता है और इच्छानुसार कम कर सकता है, जब तक कि आप कोई विशेषज्ञता नहीं लिख सकते।


3
ये अच्छे सामान्यीकरण के विचार हैं लेकिन यह उत्तर पूरी तरह से उस निशान को याद करता है जो प्रश्न में पूछा जा रहा है। यह सवाल इस बारे में नहीं है कि समाधान का सामान्यीकरण कैसे किया जाता है, लेकिन हम सामान्यीकरण पर रेखा कहां खींचते हैं और नैतिक रूप से इन विचारों का वजन कैसे करते हैं।
maple_shaft

इसलिए मैं कह रहा हूं कि आपको उन्हें उन उपयोग मामलों की संख्या से तौलना चाहिए जो वे निर्माण की जटिलता से संशोधित करते हैं। एक विधि जो एक उपयोग के मामले का समर्थन करती है वह एक विधि के रूप में मूल्यवान नहीं है जो 20 उपयोग के मामलों का समर्थन करती है। दूसरी ओर, यदि आप सभी जानते हैं कि एक उपयोग मामला है, और इसके लिए कोड करने में 5 मिनट लगते हैं - इसके लिए जाएं। अक्सर विशिष्ट तरीकों का समर्थन करने वाले कोडिंग तरीके आपको सामान्य बनाने के तरीके के बारे में सूचित करते हैं।
रोडनी पी। बारबाती 21
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.