2015-12-24 6 views
5

कई अन्य राज्य से संबंधित प्रकार के बीच, मैं अपने कोड में निम्नलिखित रिकॉर्ड प्रकार है:कॉपी गुणों के बीच रिकॉर्ड्स

type SubmittedSuggestionData = { 
    SuggestionId : Guid 
    SuggestionText : string 
    Originator : User 
    ParentCategory : Category 
    SubmissionDate : DateTime 
} 

type ApprovedSuggestionData = { 
    SuggestionId : Guid 
    SuggestionText : string 
    Originator : User 
    ParentCategory : Category 
    SubmissionDate : DateTime 
    ApprovalDate : DateTime 
} 

ये उसके बाद निम्न में फ़ीड:

type Suggestion = 
    | SubmittedSuggestion of SubmittedSuggestionData 
    | ApprovedSuggestion of ApprovedSuggestionData 

यह मैं देता राज्य पर निर्भर विशिष्ट व्यावसायिक तर्क करने के लिए राज्य मशीन शैली पैटर्न के साथ काम करने की क्षमता। (यह दृष्टिकोण से लिया गया है: http://fsharpforfunandprofit.com/posts/designing-with-types-representing-states/)

मैं एक समारोह है कि यह सरलतम रूप है में, बदल जाता है एक SubmittedSuggestion एक ApprovedSuggestion रहे हैं:

let ApproveSuggestion suggestion = 
    match suggestion with 
    | SubmittedSuggestion suggestion -> ApprovedSuggestion {} 

इस समारोह के रूप में इस समय अधूरा है मैं क्या कर रहा हूँ संघर्ष समझने के लिए जब एक स्वीकृति स्वीकृत से स्वीकृत परिवर्तन में बदलती है, तो में 10 में की नई संपत्ति को पॉप्युलेट करते समय आप suggestion में उत्तीर्ण से गुणों की प्रतिलिपि कैसे बनाते हैं?

let ApproveSuggestion suggestion = 
    match suggestion with 
    | SubmittedSuggestion {SuggestionId = suggestionId; SuggestionText = suggestionText; Originator = originator; ParentCategory = category; SubmissionDate = submissionDate} -> 
     ApprovedSuggestion {SuggestionId = suggestionId; SuggestionText = suggestionText; Originator = originator; ParentCategory = category; SubmissionDate = submissionDate; ApprovalDate = DateTime.UtcNow} 

लेकिन है कि मेरे पास बहुत भीषण दिखता है:

मैं अगर मैं कुछ ऐसा किया कि यह काम करेगा लगता है।

क्या एक ही परिणाम प्राप्त करने का एक क्लीनर, अधिक संक्षिप्त तरीका है? मैंने with कीवर्ड का उपयोग करने का प्रयास किया है लेकिन यह संकलित नहीं हुआ है।

धन्यवाद

उत्तर

6

हो जाता है वहाँ प्रकार के बीच एक बड़ी ओवरलैप है, यह अक्सर एक अच्छा विचार लगता है अपघटन के बारे में। उदाहरण के लिए, प्रकार ऐसा दिखाई दे सकता:

type SuggestionData = { 
    SuggestionId : Guid 
    SuggestionText : string 
    Originator : User 
    ParentCategory : Category 
    SubmissionDate : DateTime 
} 

type ApprovedSuggestionData = { 
    Suggestion : SuggestionData 
    ApprovalDate : DateTime 
} 

उपयोग और प्रकार के बीच मतभेद के आधार पर, एक भी दूसरे प्रकार कुल मिलाकर लंघन केवल भेदभाव संघ भीतर मंजूरी दे दी प्रकार के लिए विचार कर सकते हैं,:

type Suggestion = 
    | SubmittedSuggestion of SuggestionData 
    | ApprovedSuggestion of SuggestionData * approvalDate : DateTime 

इस तरह के अपघटन के खिलाफ एक आम तर्क यह है कि पदानुक्रम को गहराई से नीचे के प्रकार के सदस्यों तक पहुंच अधिक वर्बोज़ बन जाती है, उदाहरण के लिए approvedSuggestionData.Suggestion.Originator। हालांकि यह सच है, गुणों का उपयोग आमतौर पर घटकों के उपयोग किए जाने वाले सदस्यों को आगे बढ़ाने के लिए किया जा सकता है यदि वर्बोजिटी परेशान हो जाती है, और किसी भी नकारात्मक पक्ष को फायदे के खिलाफ वजन कम किया जाना चाहिए: प्रकारों में कम कोड डुप्लिकेशंस है, और कोई भी ऑपरेशन जो अधिक दानेदार प्रकार की पेशकश कर सकता है बना प्रकार से उपलब्ध कराया जाना चाहिए।

एक अनुमोदित सुझाव से स्वीकृत सुझाव आसानी से बनाने की क्षमता और स्वीकृति तिथि एक ऐसा मामला है जिसमें यह उपयोगी है। लेकिन और भी हो सकता है: उदाहरण के लिए, एक ऐसा ऑपरेशन है जो उपयोगकर्ताओं और सभी सुझावों की श्रेणियों को मान्य करता है, अनुमोदित या नहीं। यदि स्वीकृत और अस्वीकृत सुझावों के लिए Originator और ParentCategory सदस्यों को धारण करने वाले प्रकार असंबद्ध हैं, तो कोड को इन्हें डुप्लिकेट करने की आवश्यकता है।(या एक सामान्य इंटरफ़ेस बनाने की आवश्यकता होगी।)

+0

हमम, मुझे इस एक @ Vandroiy की तरह पसंद है। मेरे राज्य भारी रूप से भिन्न नहीं होंगे, इसलिए यह मेरे लिए एक वैध समाधान भी हो सकता है। मैं इसे एक शॉट दूंगा और आपको बता दूंगा :) – Stu1986C

4

मैं

type SubmittedSuggestionData = { 
    SuggestionId : Guid 
    SuggestionText : string 
    Originator : User 
    ParentCategory : Category 
    SubmissionDate : DateTime 
    ApprovalDate : DateTime option 
} 

को अपनी प्रतिक्रिया बदल जाएगा और उसके बाद अनुमोदन

let approve t = {t with AprovalDate =Some(System.DateTime.Now)} 
+1

धन्यवाद @ जॉन पामर। यह करने के लिए मेरे दिमाग को पार कर गया है, लेकिन मैं थोड़ी देर से लेट गया हूं क्योंकि मैंने सी # में कई बार राज्य पैटर्न का उपयोग किया है और जिस चीज ने मुझे अपने पिछले कार्यान्वयन में क्रिंग किया है, वह एक निश्चित राज्य के भीतर अनावश्यक गुणों की उपस्थिति है। आदर्श रूप में मैं एक स्वच्छ डोमेन मॉडल चाहता हूं जहां केवल प्रासंगिक गुण उनके संबंधित रिकॉर्ड प्रकारों में पाए जाते हैं। :) – Stu1986C

+0

वह संपत्ति वास्तव में "अप्रयुक्त" नहीं है, यह इंगित करती है कि सुझाव स्वीकृत है या नहीं। –

4

@ वंड्रोय और @ जॉनप्मर द्वारा प्रदान किए गए दोनों सुझाव अच्छे हैं, लेकिन पूर्णता के लिए, मैं भी एक तीसरा परिप्रेक्ष्य पेश करना चाहता हूं।

जहां तक ​​मुझे पता है, वहां कोई भाषा निर्माण नहीं है जो 'समान' प्रकारों के बीच मूल्यों की प्रतिलिपि बनायेगा। इसका कारण यह है कि इन प्रकार अलग हैं। उनकी समानता आकस्मिक है, लेकिन प्रकार प्रणाली से देखा जाता है, वे पूरी तरह से अलग प्रकार हैं। यदि आप उन्हें 'गणितीय' देखते हैं, तो वे बस A और B टाइप करते हैं।

ऐसे मामलों में, मैं अक्सर बस गोली काटने और एक अनुवाद समारोह कि अन्य प्रकार के मूल्यों को एक प्रकार के मूल्यों तब्दील जोड़ेंगे: हालांकि यह एक छोटे से वर्बोज़ लगता

let approve (suggestion : SubmittedSuggestionData) = { 
    SuggestionId = suggestion.SuggestionId 
    SuggestionText = suggestion.SuggestionText 
    Originator = suggestion.Originator 
    ParentCategory = suggestion.ParentCategory 
    SubmissionDate = suggestion.SubmissionDate 
    ApprovalDate = DateTime.UtcNow } 

, आप अभी भी इसे DRY रखते हैं क्योंकि मानों की प्रतिलिपि उस एकल फ़ंक्शन पर बाध्य होती है।

इसके अलावा, इस तरह के एक समारोह को अक्सर एक अच्छा नाम दिया जा सकता है, जिसका अर्थ है कि यह कार्य आपके डोमेन मॉडल का हिस्सा बन जाता है।

संबंधित मुद्दे