Question

So I'm a total Scala noob and come from a rusty Java background and a primarily PHP+JavaScript one. I'm finding myself getting frustrated, because there are design patterns I want to implement in Scala but I have no idea how, WHich leads to a lot of reading, and never any programming.

Anyway so I am busy making a basic program to learn the ins and outs, and I am making a configuration file reader. What i need to do is map different formats to extensions, the trick being that different extensions such as yaml and yml map to the same format.

In java I would use Enums and control the mapping in the constructor. Pretty straight forward.

In scala ... not so much. First I discover that ADT (meaning Algebraic Data Types not Abstract Data Types) is a better alternative then the use of Enumeration (reasons for which are still not clear to me), and it works better with Java libraries (ironically, and I have no idea why.)

Next I discover the various formats of ADT, and as a beginner grasping all the concepts simultaneously is strenuous. I have managed to figure out that the companion Objects are similar to javascript in the sense that it is a single instantiation almost like a singleton and allows you to access the defined functions in a static context.


Now back to the problem

I've written what I thought was a good idea, but the code looks cumbersome, verbose, and I can't figure out some use cases, and It appears from all my JS plugin writing I'm a bit of a namespacing nut that does well for logical separation but not conciseness in scala.

class ConfigManager {
  object Formats{
    case class Format(f: String){
      val format = f.toUpperCase()
    }
    case object Yaml extends Format("YAML")
    case object Xml  extends Format("XML")
    case object Json extends Format("JSON")
  }

  object Extensions {
    case class Extension(e: String) {
      val extension = e.toUpperCase()
    }
    case object Yaml extends Extension("YAML")
    case object Yml  extends Extension("YML")
    case object Xml  extends Extension("XML")
    case object Json extends Extension("JSON")
  }


  object Config {
    private sealed trait ConfigFormats {
      def f: Formats.Format
      def e : Extensions.Extension
    }
    case class ConfigFormat(f: Formats.Format, e: Extensions.Extension) 
            extends ConfigFormats (f, e)

    case object Yaml1 extends ConfigFormat(Formats.Yaml, Extensions.Yaml)
    case object Yaml2 extends ConfigFormat(Formats.Yaml, Extensions.Yml)
    case object Xml   extends ConfigFormat(Formats.Xml, Extensions.Xml)
    case object Json  extends ConfigFormat(Formats.Json, Extensions.Json)
  }

  //this looks nice, and useful, is concise and does what I want
  def readConfig(c: Config.ConfigFormat){
    c.f match {
      case Formats.Yaml => readConfigYaml()
      case Formats.Json => readConfigJson()
      case Formats.Xml  => readConfigXml()
      case _ => throw new Exception("Invalid Config format")
    }
  }

  //and this is where I lose the plot
  def setFormat(extension: String){
    val configFormat = new Extensions.Extension(discoveredFormat) match {
      case Config.????? => ????
    }
  }
}

So the obvious question is how bad exactly is my implementation, and what should I have done, and why? (I'm most concerned about the "Why")

Was it helpful?

Solution

Scala Enums are fine, you could define Formats and Extensions like this:

object Formats extends Enumeration {
  type Eny = Value
  val YAML, XML, JSON = Value
}
object Extensions extends Enumeration {
  type Eny = Value
  val YAML, YML, XML, JSON = Value
}

And if you want to a map, just use a map:

val configFormats: Map[Extensions.Value, Formats.Value] = Map(
  Extensions.YAML -> Formats.YAML,
  Extensions.YML  -> Formats.YAML,
  Extensions.XML  -> Formats.XML,
  Extensions.JSON -> Formats.JSON)

Then I'm not really sure of what your methods are supposed to do, but it looks like your setFormat could start like this:

def setFormat(extension: String): Unit = {
  val format: Formats.Value = configFormats(Extensions withName extension)
  ...
}

You see, just like Java :) If you describe better what you are trying to do we might be able to give you a more "idiomatic way".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top