2011-10-08 25 views
11

Şu anda Scala ile deneme ve en iyi uygulamaları arıyorum. Tek bir problemi çözmek için kendime iki zıt yaklaşımın olduğunu buldum. Hangisinin daha iyi olduğunu ve neden daha konvansiyonel olduğunu bilmek isterdim ve belki başka bazı daha iyi yaklaşımları biliyor olsaydınız. İkincisi bana daha güzel görünüyor.Scala En İyi Uygulama: Trait Inheritance - Enumeration

1. Sayım tabanlı çözüm

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. Singleton tabanlı çözüm

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 
    } 
    } 
} 

cevap

12

:) + 1'e düşünün lütfen, ayrıntılı olma ile üzerine yapabilirsiniz desen maçı kontrol (yani, bir vaka unutursanız Scala size söyleyecektir).

Neyse, Scala'nın Enumeration sevmediğim, ve zor yalnız değilim. Onu asla kullanmam, ve sayımın gerçekten en temiz çözüm olduğu bir şey varsa, Java'nın numaralandırmasını kullanarak sadece Java'da yazmak daha iyidir. Gerçekten her veritabanı türü için sınıflar gerekmez bu özellikle durum için

+0

Tamamen katılıyorum. Scala numaralandırmalar kesinlikle işe yaramaz. Sadece birinin ihtiyaç duyduğundan şüphelenen sıralı değerlerin otomatik üretimini sağlıyorlar. Aksine, dize kimliği ile bir değer aramak için iyi bir yol (yansıma altında kullanılmaktadır) bulunmaktadır ve Numaralama # Değerinden Numaralama çözmek için hiçbir yasal yolu yoktur. –

4

daha anlaşılır subclassing verir beri, tekil varyant için gider.

Ayrıca bazı sorgular/alt sorgular beri/operatörler farklı olabilir, db özgü şeyler/geçersiz kılmaları yapmak gerekebilir.

Ama ben böyle bir şey denemek istiyorum: Bu yardım edersem

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 
    } 

} 

, bir sealed trait DBType bildirirseniz bu

+0

Özellikleri parametreleri olamaz. Bu soyut bir sınıf mıydı? –

+0

evet üzgünüm, sadece kodunuzu kopyaladım ve oradaki özelliği unuttum. –

+0

Yani mojojojo'nun kodunu kopyaladın. –

10

; sadece veri. Gerçek durum dramatik daha karmaşık sürece, kod tekrarına miktarını en aza indirmek için bir harita ve dize ayrıştırma tabanlı çözüm kullanırsınız:

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)) 
    } 
}