2011-10-08 14 views
11

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

1. गणन आधारित समाधान

import org.squeryl.internals.DatabaseAdapter 
import org.squeryl.adapters.{H2Adapter, MySQLAdapter, PostgreSqlAdapter} 
import java.sql.Driver 

object DBType extends Enumeration { 
    val MySql, PostgreSql, H2 = Value 

    def fromUrl(url: String) = { 
    url match { 
     case u if u.startsWith("jdbc:mysql:") => Some(MySql) 
     case u if u.startsWith("jdbc:postgresql:") => Some(PostgreSql) 
     case u if u.startsWith("jdbc:h2:") => Some(H2) 
     case _ => None 
    } 
    } 
} 

case class DBType(typ: DBType) { 
    lazy val driver: Driver = { 
    val name = typ match { 
     case DBType.MySql => "com.mysql.jdbc.Driver" 
     case DBType.PostgreSql => "org.postgresql.Driver" 
     case DBType.H2 => "org.h2.Driver" 
    } 
    Class.forName(name).newInstance().asInstanceOf[Driver] 
    } 
    lazy val adapter: DatabaseAdapter = { 
    typ match { 
     case DBType.MySql => new MySQLAdapter 
     case DBType.PostgreSql => new PostgreSqlAdapter 
     case DBType.H2 => new H2Adapter 
    } 
    } 
} 

2. सिंगलटन आधारित समाधान

import org.squeryl.internals.DatabaseAdapter 
import org.squeryl.adapters.{H2Adapter, MySQLAdapter, PostgreSqlAdapter} 
import java.sql.Driver 

trait DBType { 
    def driver: Driver 
    def adapter: DatabaseAdapter 
} 

object DBType { 
    object MySql extends DBType { 
    lazy val driver = Class.forName("com.mysql.jdbc.Driver").newInstance().asInstanceOf[Driver] 
    lazy val adapter = new MySQLAdapter 
    } 

    object PostgreSql extends DBType { 
    lazy val driver = Class.forName("org.postgresql.Driver").newInstance().asInstanceOf[Driver] 
    lazy val adapter = new PostgreSqlAdapter 
    } 

    object H2 extends DBType { 
    lazy val driver = Class.forName("org.h2.Driver").newInstance().asInstanceOf[Driver] 
    lazy val adapter = new H2Adapter 
    } 

    def fromUrl(url: String) = { 
    url match { 
     case u if u.startsWith("jdbc:mysql:") => Some(MySql) 
     case u if u.startsWith("jdbc:postgresql:") => Some(PostgreSql) 
     case u if u.startsWith("jdbc:h2:") => Some(H2) 
     case _ => None 
    } 
    } 
} 

उत्तर

12

आप एक sealed trait DBType घोषित करते हैं, तो exhaustiveness के साथ इस पर आप पैटर्न मैच कर सकते हैं जांच (यानी, यदि आप एक मामले को भूल जाते हैं तो स्कैला आपको बताएगी)।

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

+0

मैं पूरी तरह से सहमत हूं। स्कैला गणना बिल्कुल बेकार हैं। वे केवल अनुक्रमिक मूल्यों की स्वत: पीढ़ी प्रदान करते हैं, जो मुझे संदेह है कि किसी को भी जरूरत है। इसके विपरीत, स्ट्रिंग आईडी द्वारा मूल्य को देखने का कोई अच्छा तरीका नहीं है (प्रतिबिंब नीचे नियोजित किया गया है) और गणना # मूल्य से गणना को हल करने का कोई कानूनी तरीका नहीं है। –

4

मैं, सिंगलटन संस्करण के लिए जाना चाहते हैं, क्योंकि यह स्पष्ट उपवर्गीकरण अनुमति देता है।

इसके अलावा, आप db-विशिष्ट बातें/ओवरराइड करने के लिए आवश्यकता हो सकती है, कुछ क्वेरी/सबक्वेरी के बाद से/ऑपरेटरों अलग हो सकता है।

लेकिन मैं कुछ इस तरह की कोशिश करेंगे:

import org.squeryl.internals.DatabaseAdapter 
import org.squeryl.adapters.{H2Adapter, MySQLAdapter, PostgreSqlAdapter} 
import java.sql.Driver 

abstract class DBType(jdbcDriver: String) { 
    lazy val driver = Class.forName(jdbcDriver).newInstance().asInstanceOf[Driver] 
    def adapter: DatabaseAdapter 
} 


object DBType { 
    object MySql extends DBType("com.mysql.jdbc.Driver") { 
    lazy val adapter = new MySQLAdapter 
    } 

    object PostgreSql extends DBType("org.postgresql.Driver") { 
    lazy val adapter = new PostgreSqlAdapter 
    } 

    object H2 extends DBType("org.h2.Driver") { 
    lazy val adapter = new H2Adapter 
    } 

    def fromUrl(url: String) = { 
    url match { 
     case _ if url.startsWith("jdbc:mysql:") => Some(MySql(url)) 
     case _ if url.startsWith("jdbc:postgresql:") => Some(PostgreSql(url)) 
     case _ if url.startsWith("jdbc:h2:") => Some(H2(url)) 
     case _ => None 
    } 

} 

अगर यह मदद की, +1 करने पर विचार करें इस :)

+0

लक्षणों में पैरामीटर नहीं हो सकते हैं। क्या यह एक अमूर्त वर्ग होना चाहिए था? –

+0

हाँ माफ करना, मैं सिर्फ अपने कोड की नकल की और वहाँ विशेषता के बारे में भूल गया था। –

+0

आपका मतलब है कि आपने mojojojo का कोड कॉपी किया है। –

10

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

case class DBRecord(url: String, driver: String, adapter:() => DatabaseAdapter) {} 

class DBType(record: DBRecord) { 
    lazy val driver = Class.forName(record.driver).newInstance().asInstanceOf[Driver] 
    lazy val adapter = record.adapter() 
} 

object DBType { 
    val knownDB = List(
    DBRecord("mysql", "com.mysql.jdbc.Driver",() => new MySQLAdapter), 
    DBRecord("postgresql", "org.postgresql.Driver",() => new PostgreSqlAdapter), 
    DBRecord("h2", "org.h2.Driver",() => new H2Adapter) 
) 

    val urlLookup = knownDB.map(rec => rec.url -> rec).toMap 

    def fromURL(url: String) = { 
    val parts = url.split(':') 
    if (parts.length < 3 || parts(0) != "jdbc") None 
    else urlLookup.get(parts(1)).map(rec => new DBType(rec)) 
    } 
} 
संबंधित मुद्दे