अवलंबित्व उलथापालथ तत्त्व वापरून अंमलात आणले जाते. अवलंबित्व उलथापालथ

मुख्यपृष्ठ / भांडण

खरं तर, सर्व तत्त्वे घनमजबूतपणे एकमेकांशी जोडलेले आहेत आणि उच्च-गुणवत्तेचे, स्केलेबल सॉफ्टवेअर तयार करण्यात मदत करणे हे त्यांचे मुख्य लक्ष्य आहे. पण शेवटचे तत्व घनखरोखर त्यांच्या विरोधात उभे आहे. प्रथम, या तत्त्वाची रचना पाहू. तर, अवलंबित्व उलथापालथ तत्त्व (अवलंबन उलथापालथ तत्त्व - DIP): "अमूर्त गोष्टींवर अवलंबित्व. विशिष्ट कशावरही अवलंबून नाही.. कुख्यात सॉफ्टवेअर डेव्हलपमेंट तज्ज्ञ, रॉबर्ट मार्टिन यांनीही तत्त्वावर प्रकाश टाकला DIPआणि इतर तत्त्वांचे पालन केल्यामुळे ते फक्त सादर करते घन- खुले/बंद तत्त्व आणि लिस्कोव्ह प्रतिस्थापन तत्त्व. लक्षात ठेवा की प्रथम असे म्हणते की नवीन बदल करण्यासाठी वर्गात बदल करू नयेत आणि दुसरा वारशाशी संबंधित आहे आणि प्रोग्रामच्या योग्य ऑपरेशनला खंडित न करता काही बेस प्रकारच्या व्युत्पन्न प्रकारांचा सुरक्षित वापर गृहीत धरतो. रॉबर्ट मार्टिनने मूलतः हे तत्त्व खालीलप्रमाणे तयार केले:

एक). उच्च-स्तरीय मॉड्यूल्स निम्न-स्तरीय मॉड्यूल्सवर अवलंबून नसावेत. दोन्ही स्तरांवरील मॉड्यूल्स अमूर्तांवर अवलंबून असणे आवश्यक आहे.

२). अॅब्स्ट्रॅक्शन तपशीलांवर अवलंबून नसावेत. तपशील अमूर्ततेवर अवलंबून असले पाहिजेत.

म्हणजेच, अमूर्ततेच्या दृष्टीने वर्ग विकसित करणे आवश्यक आहे, त्यांची विशिष्ट अंमलबजावणी नाही. आणि जर तुम्ही तत्त्वांचे पालन केले तर OCPआणि LSP, मग आपण हेच साध्य करू. म्हणून, यावरील धड्याकडे थोडे मागे जाऊया. तेथे, उदाहरण म्हणून, आम्ही वर्गाचा विचार केला बार्ड, जे अगदी सुरुवातीला वर्गासाठी कठीण होते गिटार, एका विशिष्ट वाद्याचे प्रतिनिधित्व करत आहे:

सार्वजनिक वर्ग बार्ड (खाजगी गिटार गिटार; सार्वजनिक बार्ड(गिटार गिटार) ( this.guitar = गिटार; ) सार्वजनिक शून्य प्ले() ( guitar.play(); ) )

सार्वजनिक वर्ग बार्ड(

खाजगी गिटार गिटार;

सार्वजनिक बार्ड (गिटार गिटार)

हे गिटार = गिटार;

सार्वजनिक शून्य खेळ()

गिटार प्ले();

जर आम्हाला या वर्गात इतर वाद्य वाद्यांचा आधार जोडायचा असेल तर आम्हाला या वर्गात कसा तरी बदल करावा लागेल. हे तत्त्वाचे स्पष्ट उल्लंघन आहे OCP. आणि तुमच्या लक्षात आले असेल की हे देखील तत्त्वाचे उल्लंघन आहेत DIP, कारण आमच्या बाबतीत आमची अमूर्तता तपशीलांवर अवलंबून असल्याचे दिसून आले. आमच्या वर्गाच्या पुढील विस्ताराच्या दृष्टिकोनातून, हे अजिबात चांगले नाही. आमचा वर्ग तत्त्वाच्या अटी पूर्ण करण्यासाठी OCPआम्ही सिस्टममध्ये इंटरफेस जोडला आहे साधन, ज्याने विशिष्ट प्रकारचे वाद्य यंत्रांचे प्रतिनिधित्व करणारे विशिष्ट वर्ग लागू केले.

फाईल साधन.जावा:

सार्वजनिक इंटरफेस इन्स्ट्रुमेंट (व्हॉइड प्ले();)

सार्वजनिक इंटरफेस साधन(

voidplay();

फाईल गिटार.जावा:

क्लास गिटार इन्स्ट्रुमेंट (@Override public void play() ( System.out.println("गिटार प्ले करा!"); ) )

क्लास गिटार इन्स्ट्रुमेंट

@ओव्हरराइड

सार्वजनिक शून्य खेळ()

प्रणाली. बाहेर println("गिटार प्ले!");

फाईल lute.java:

सार्वजनिक वर्ग Lute इन्स्ट्रुमेंट (@Override public void play() ( System.out.println("Play Lute!"); )

पब्लिक क्लास ल्यूट इम्प्लुमेंट्स इन्स्ट्रुमेंट(

@ओव्हरराइड

सार्वजनिक शून्य खेळ()

प्रणाली. बाहेर println("प्ले ल्यूट!");

त्यानंतर आम्ही वर्ग बदलला बार्डजेणेकरुन, आवश्यक असल्यास, आम्ही आम्हाला आवश्यक असलेल्या अंमलबजावणीसह पुनर्स्थित करू शकतो. हे तयार होत असलेल्या प्रणालीमध्ये अतिरिक्त लवचिकता आणते आणि तिची सुसंगतता (एकमेकांवर मजबूत वर्ग अवलंबित्व) कमी करते.

पब्लिक क्लास बार्ड (खाजगी इन्स्ट्रुमेंट इन्स्ट्रुमेंट; पब्लिक बार्ड() () पब्लिक व्हॉईड प्ले() (इन्स्ट्रुमेंट.प्ले(); ) पब्लिक व्हॉईड सेट इन्स्ट्रुमेंट(इन्स्ट्रुमेंट इन्स्ट्रुमेंट) ( this.instrument = इन्स्ट्रुमेंट; ) )

सार्वजनिक वर्ग बार्ड(

खाजगी साधन साधन;

2 प्रत्युत्तरे

चांगला मुद्दा - उलथापालथ हा शब्द काहीसा आश्चर्यकारक आहे (डीआयपी लागू केल्यानंतर, खालच्या-स्तरीय अवलंबित्व मॉड्यूल वरवर पाहता आता उच्च-स्तरीय कॉलर मॉड्यूलवर अवलंबून नाही: एकतर कॉलर किंवा आश्रित आता एका अतिरिक्त अमूर्ततेद्वारे अधिक सैलपणे जोडले गेले आहे. ).

मी "उलटा" हा शब्द का वापरतो हे तुम्ही विचाराल. खरे सांगायचे तर, याचे कारण असे की संरचित विश्लेषण आणि डिझाइन यासारख्या अधिक पारंपारिक सॉफ्टवेअर विकास पद्धती सॉफ्टवेअर संरचना तयार करतात ज्यामध्ये उच्च-स्तरीय मॉड्यूल निम्न-स्तरीय मॉड्यूल्सवर अवलंबून असतात आणि ज्यामध्ये अमूर्तता तपशीलांवर अवलंबून असतात. खरं तर, या पद्धतींचा एक उद्देश म्हणजे सबरूटीनची पदानुक्रम परिभाषित करणे जे उच्च-स्तरीय मॉड्यूल निम्न-स्तरीय मॉड्यूल्सना कसे कॉल करतात याचे वर्णन करतात.... अशा प्रकारे, सु-डिझाइन केलेल्या ऑब्जेक्ट-ओरिएंटेड प्रोग्रामची अवलंबित्व संरचना आहे. अवलंबित्व संरचनेच्या संदर्भात "उलटलेले", जे सहसा पारंपारिक प्रक्रियात्मक पद्धतींचे परिणाम असते.

अंकल बॉबचा DIP वरचा पेपर वाचताना लक्षात घेण्याजोगा मुद्दा असा आहे की C++ मध्ये इंटरफेस नसतात (आणि लिहिण्याच्या वेळी, नसते) त्यामुळे C++ मध्ये हे अ‍ॅब्स्ट्रॅक्शन साध्य करणे सामान्यतः अ‍ॅबस्ट्रॅक्ट/प्युअर व्हर्च्युअल बेस क्लासद्वारे साध्य केले जाते, तर Java मध्ये किंवा C# कपलिंग सैल करण्यासाठी अ‍ॅब्स्ट्रॅक्शन म्हणजे इंटरफेसला अवलंबित्वापासून अ‍ॅबस्ट्रॅक्ट करून आणि इंटरफेसला उच्च स्तरीय मॉड्यूल(चे) बंधनकारक करून अनबाइंड करणे.

सुधारणेफक्त स्पष्ट करण्यासाठी:

"काही ठिकाणी मला असे दिसते की याला अवलंबित्व व्युत्क्रमण म्हणतात"

उलथापालथ:अवलंबित्व व्यवस्थापन अॅप्लिकेशनपासून कंटेनरमध्ये उलटा (जसे स्प्रिंग).

अवलंबित्व इंजेक्शन:

फॅक्टरी पॅटर्न लिहिण्याऐवजी, क्लायंट क्लासमध्ये थेट ऑब्जेक्ट इंजेक्ट करणे कसे आहे. चला क्लायंट क्लासला इंटरफेसचा संदर्भ देऊ या आणि आपण क्लायंट क्लासमध्ये ठोस प्रकार इंजेक्ट करू शकू. यासह, क्लायंट क्लासला नवीन कीवर्ड वापरण्याची आवश्यकता नाही आणि तो पूर्णपणे ठोस वर्गांपासून विभक्त झाला आहे.

इन्व्हर्शन ऑफ कंट्रोल (IoC) चे काय?

पारंपारिक प्रोग्रामिंगमध्ये, व्यवसाय तर्कशास्त्राचा प्रवाह स्थिरपणे एकमेकांना नियुक्त केलेल्या वस्तूंद्वारे परिभाषित केला जातो. नियंत्रणाच्या उलथापालथीसह, प्रवाह एका ऑब्जेक्ट आलेखावर अवलंबून असतो जो असेंबलरद्वारे इन्स्टंट केला जातो आणि अॅब्स्ट्रॅक्शनद्वारे परिभाषित केलेल्या ऑब्जेक्टच्या परस्परसंवादामुळे शक्य होतो. बंडलिंग प्रक्रिया अवलंबित्व इंजेक्शनद्वारे साध्य केली जाते, जरी काही लोक असा युक्तिवाद करतात की सर्व्हिस लोकेटर वापरणे देखील नियंत्रणाचे उलट प्रदान करते.

डिझाईन मार्गदर्शक म्हणून नियंत्रणाचे उलथापालथ खालील उद्देशांसाठी करते:

  • अंमलबजावणीपासून विशिष्ट कार्याच्या अंमलबजावणीचे एक डीकपलिंग आहे.
  • प्रत्येक मॉड्यूल ते कशासाठी आहे यावर लक्ष केंद्रित करू शकते.
  • मॉड्यूल इतर प्रणाली काय करतात याबद्दल कोणतीही गृहितक करत नाहीत, परंतु त्यांच्या करारांवर अवलंबून असतात.
  • मॉड्यूल्स बदलल्याने इतर मॉड्यूल्सवर परिणाम होत नाही.

अधिक माहितीसाठी पहा.

शेवटचे अपडेट: 03/11/2016

अवलंबित्व उलथापालथ तत्त्व(डिपेंडेंसी इन्व्हर्शन प्रिन्सिपल) चा वापर सहजतेने जोडलेल्या घटक तयार करण्यासाठी केला जातो ज्याची चाचणी करणे, सुधारणे आणि अपडेट करणे सोपे आहे. हे तत्त्व खालीलप्रमाणे तयार केले जाऊ शकते:

शीर्ष-स्तरीय मॉड्यूल्स निम्न-स्तरीय मॉड्यूल्सवर अवलंबून नसावेत. दोन्ही अमूर्ततेवर अवलंबून असणे आवश्यक आहे.

अॅब्स्ट्रॅक्शन तपशीलांवर अवलंबून नसावेत. तपशील अमूर्ततेवर अवलंबून असले पाहिजेत.

तत्त्व समजून घेण्यासाठी, खालील उदाहरणाचा विचार करा:

वर्ग पुस्तक ( सार्वजनिक स्ट्रिंग मजकूर ( मिळवा; सेट; ) सार्वजनिक कन्सोलप्रिंटर प्रिंटर ( मिळवा; सेट; ) सार्वजनिक शून्य प्रिंट () ( प्रिंटर. प्रिंट (मजकूर); ) ) वर्ग कन्सोलप्रिंटर ( सार्वजनिक शून्य प्रिंट (स्ट्रिंग मजकूर) ( कन्सोल.WriteLine (मजकूर); ))

पुस्तक वर्ग, जो पुस्तकाचे प्रतिनिधित्व करतो, मुद्रण करण्यासाठी कन्सोलप्रिंटर वर्ग वापरतो. अशा प्रकारे परिभाषित केल्यावर, पुस्तक वर्ग कन्सोलप्रिंटर वर्गावर अवलंबून असतो. शिवाय, आम्ही कठोरपणे परिभाषित केले आहे की कन्सोल प्रिंटर क्लास वापरून कन्सोलवर पुस्तक मुद्रित करणे शक्य आहे. इतर पर्याय, उदाहरणार्थ, प्रिंटरचे आउटपुट, फाईलचे आउटपुट किंवा ग्राफिकल इंटरफेसचे काही घटक वापरणे - हे सर्व या प्रकरणात वगळले आहे. कन्सोलप्रिंटर वर्गाच्या तपशिलांपासून पुस्तक प्रिंटिंग अॅब्स्ट्रॅक्शन वेगळे नाही. हे सर्व अवलंबित्व उलथापालथ तत्त्वाचे उल्लंघन आहे.

आता निम्न-स्तरीय अंमलबजावणीपासून अ‍ॅब्स्ट्रॅक्शन्स विभक्त करून अवलंबित्व उलथापालथ तत्त्वानुसार आमचे वर्ग आणण्याचा प्रयत्न करूया:

इंटरफेस IPprinter ( void Print(string text); ) वर्ग पुस्तक ( सार्वजनिक स्ट्रिंग मजकूर ( मिळवा; सेट; ) सार्वजनिक IPprinter प्रिंटर ( मिळवा; सेट; ) सार्वजनिक पुस्तक (आयपीप्रिंटर प्रिंटर) ( हे. प्रिंटर = प्रिंटर; ) सार्वजनिक शून्य प्रिंट ( ) ( Printer.Print(Text); ) ) वर्ग कन्सोलप्रिंटर: IPprinter ( सार्वजनिक शून्य मुद्रण(स्ट्रिंग मजकूर) ( कन्सोल.WriteLine("कन्सोलवर मुद्रण करा"); ) ) वर्ग HtmlPrinter: IPrinter ( सार्वजनिक शून्य मुद्रण (स्ट्रिंग मजकूर) ( Console.WriteLine("html वर प्रिंट करा"); ) )

आता पुस्तक प्रिंटिंग अॅब्स्ट्रॅक्शन ठोस अंमलबजावणीपासून वेगळे केले आहे. परिणामी, बुक क्लास आणि कन्सोलप्रिंटर क्लास दोन्ही आयप्रिंटर अॅब्स्ट्रॅक्शनवर अवलंबून असतात. याशिवाय, आता आम्ही IPrinter अ‍ॅबस्ट्रॅक्शनची अतिरिक्त निम्न-स्तरीय अंमलबजावणी देखील तयार करू शकतो आणि त्यांना प्रोग्राममध्ये गतिमानपणे लागू करू शकतो:

पुस्तक पुस्तक = नवीन पुस्तक(नवीन कन्सोलप्रिंटर()); book.Print(); book.Printer = नवीन HtmlPrinter(); book.Print();

डिपेंडेंसी इनव्हर्शन हा सर्वात महत्वाचा प्रोग्रामिंग मुहावरा आहे. रशियन-भाषेच्या इंटरनेटवर या मुहावरेचे (तत्त्व) आश्चर्यकारकपणे काही वर्णन आहेत. म्हणून मी वर्णन करण्याचा प्रयत्न करण्याचा निर्णय घेतला. मी जावामध्ये उदाहरणे देईन, या क्षणी माझ्यासाठी हे सोपे आहे, जरी अवलंबित्व व्युत्क्रमणाचे तत्त्व कोणत्याही प्रोग्रामिंग भाषेला लागू आहे.

हे वर्णन व्लादिमीर मातवीव यांच्यासोबत संयुक्तपणे जावा विद्यार्थ्यांसह वर्गांच्या तयारीसाठी विकसित केले गेले.

या मालिकेतील इतर लेख:

चला "अवलंबन" च्या व्याख्येसह प्रारंभ करूया. व्यसन म्हणजे काय? जर तुमचा कोड काही क्लास अंतर्गत वापरत असेल किंवा स्पष्टपणे काही क्लास किंवा फंक्शनची स्टॅटिक पद्धत कॉल करत असेल, तर हे अवलंबित्व आहे. मी उदाहरणांसह स्पष्ट करू:

वर्ग A च्या खाली someMethod() नावाच्या पद्धतीमध्ये स्पष्टपणे वर्ग B चे एक ऑब्जेक्ट तयार करते आणि तिची पद्धत someMethodOfB() ऍक्सेस करते

सार्वजनिक वर्ग A ( void someMethod() ( B b = new B(); b.someMethodOfB(); ) )

त्याचप्रमाणे, उदाहरणार्थ, क्लास बी स्पष्टपणे सिस्टम क्लासच्या स्थिर फील्ड आणि पद्धतींचा संदर्भ देते:

सार्वजनिक वर्ग ब ( void someMethodOfB() ( System.out.println("हॅलो वर्ल्ड"); ) )

सर्व प्रकरणांमध्ये जेथे कोणताही वर्ग (प्रकार A) स्वतः कोणताही वर्ग (प्रकार B) तयार करतो किंवा स्पष्टपणे स्थिर फील्ड किंवा वर्ग सदस्यांमध्ये प्रवेश करतो, याला म्हणतात सरळव्यसन त्या. महत्वाचे: जर स्वतःच्या आत असलेला वर्ग दुसर्‍या वर्गाबरोबर काम करतो, तर हे अवलंबित्व आहे. जर त्याने हा वर्ग स्वतःच्या आत निर्माण केला तर हा सरळव्यसन

थेट अवलंबनात काय चूक आहे? थेट अवलंबित्व वाईट आहे कारण जो वर्ग स्वतंत्रपणे स्वतःमध्ये दुसरा वर्ग निर्माण करतो तो या वर्गाशी "घट्ट" बांधला जातो. त्या. जर हे स्पष्टपणे लिहिले असेल की B = नवीन B(); , तर वर्ग A नेहमी B वर्गासह कार्य करेल आणि इतर वर्ग नाही. किंवा जर ते System.out.println("...") म्हणत असेल; मग वर्ग नेहमी System.out वर आउटपुट करेल आणि इतर कोठेही नाही.

लहान वर्गांसाठी, अवलंबित्व भयंकर नाही. असा कोड चांगला कार्य करू शकतो. परंतु काही प्रकरणांमध्ये, तुमचा वर्ग A विविध वर्गांच्या वातावरणात सार्वत्रिकपणे कार्य करण्यासाठी, त्याला अवलंबित्व वर्गांच्या इतर अंमलबजावणीची आवश्यकता असू शकते. त्या. तुम्हाला, उदाहरणार्थ, वर्ग B ची गरज नाही, परंतु समान इंटरफेससह दुसरा वर्ग आवश्यक आहे, किंवा System.out नाही, परंतु, उदाहरणार्थ, लॉगरवर आउटपुट (उदाहरणार्थ, log4j).

थेट अवलंबित्व याप्रमाणे ग्राफिकरित्या प्रदर्शित केले जाऊ शकते:

त्या. जेव्हा तुम्ही तुमच्या कोडमध्ये A वर्ग तयार करता: A a = नवीन A(); खरं तर, एक वर्ग A तयार केला जात नाही, तर अवलंबून असलेल्या वर्गांची संपूर्ण पदानुक्रम तयार केली जाते, ज्याचे उदाहरण वरील चित्रात आहे. ही पदानुक्रम "कठोर" आहे: वैयक्तिक वर्गांचा स्त्रोत कोड न बदलता, पदानुक्रमातील कोणताही वर्ग बदलला जाऊ शकत नाही. म्हणून, अशा अंमलबजावणीमधील वर्ग अ बदलत्या वातावरणास अनुकूल नाही. बहुधा, आपण ज्यासाठी ते लिहिले आहे त्या विशिष्ट व्यतिरिक्त, कोणत्याही कोडमध्ये ते वापरणे शक्य होणार नाही.

विशिष्ट अवलंबनांमधून वर्ग A दुप्पट करण्यासाठी, अर्ज करा अवलंबित्व इंजेक्शन. अवलंबित्व इंजेक्शन म्हणजे काय? कोडमध्ये स्पष्टपणे इच्छित वर्ग तयार करण्याऐवजी, अवलंबन कन्स्ट्रक्टरद्वारे वर्ग A मध्ये पास केले जाते:

सार्वजनिक वर्ग A ( खाजगी अंतिम B b; सार्वजनिक A(B b) ( this.b = b; ) सार्वजनिक शून्य someMethod() ( b.someMethodOfB(); ) )

ते. क्लास A ला आता कन्स्ट्रक्टर द्वारे त्याची अवलंबित्व मिळते. आता, A वर्ग तयार करण्यासाठी, तुम्हाला प्रथम त्याचा अवलंबित वर्ग तयार करावा लागेल. या प्रकरणात, हे बी आहे:

B b = नवीन B(); A a = नवीन A(b); a.someMethod();

सर्व वर्गांसाठी समान प्रक्रिया पुनरावृत्ती झाल्यास, म्हणजे. वर्ग D चे उदाहरण वर्ग B च्या कन्स्ट्रक्टरला, वर्ग D च्या कन्स्ट्रक्टरकडे - त्याची अवलंबन E आणि F, इत्यादी, नंतर तुम्हाला कोड मिळेल, ज्याचे सर्व अवलंबन उलट क्रमाने तयार केले आहेत:

G g = नवीन G(); H h = नवीन H(); F f = new(g,h); ई ई = नवीन ई(); D d = नवीन D(e,f); B b = नवीन B(d); A a = नवीन A(b); a.someMethod();

ग्राफिकदृष्ट्या, हे असे प्रदर्शित केले जाऊ शकते:

आपण 2 चित्रांची तुलना केल्यास - वरील चित्र थेट अवलंबनांसह आणि दुसरे चित्र अवलंबन इंजेक्शनसह - आपण पाहू शकता की बाणांची दिशा उलट बदलली आहे. या कारणास्तव, मुहावरेला "अवलंबन उलट" म्हणतात. दुसऱ्या शब्दांत, अवलंबित्व व्युत्क्रमण या वस्तुस्थितीमध्ये आहे की वर्ग स्वतःहून अवलंबित्व निर्माण करत नाही, परंतु त्यांना कन्स्ट्रक्टरमध्ये (किंवा अन्यथा) तयार केलेल्या स्वरूपात प्राप्त करतो.

अवलंबित्व व्युत्क्रमण चांगले का आहे? अवलंबित्व उलथापालथ सह, तुम्ही वर्गातील सर्व अवलंबनांचा कोड न बदलता बदलू शकता. आणि याचा अर्थ असा आहे की तुमचा वर्ग A हा मूळतः ज्या प्रोग्रामसाठी लिहिला होता त्यापेक्षा दुसर्‍या प्रोग्राममध्ये वापरण्यासाठी लवचिकपणे कॉन्फिगर केला जाऊ शकतो. ते. लवचिक, मॉड्यूलर, पुन्हा वापरता येण्याजोगे कोड तयार करण्यासाठी अवलंबित्व उलथापालथाचे तत्त्व (कधीकधी अवलंबित्व इंजेक्शनचे सिद्धांत म्हटले जाते) हे महत्त्वाचे आहे.

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

© 2022 skudelnica.ru -- प्रेम, विश्वासघात, मानसशास्त्र, घटस्फोट, भावना, भांडणे