2013-03-29 24 views
2

解析策略所以昨天我有一个日志文件其中有中,提供的log.txt的逗号分隔的条目,如下:登录使用Scala的

entry1.1,entry1.2,entry1.3 
entry2.1,entry2,2,entry2.3 
.......................... 

因此,与很多快乐,我继续创建了一个案例类:

case class LogEntry(
    entry1:String, 
    entry2:String, 
    entry3:String 
) 

而且在阅读的情况下填充类的情况下类,如下所示:

line.split match { 
    case Array(entry1,entry2,entry3) => LogEntry(entry1,entry2,entry3) 
} 

现在问题出现时,我今天运行我的代码,我注意到LogEntry对象没有被创建。

我看着log.txt的今天提供给我,意识到条目已经改变:

我现在有:

entry1.1,entry1.2,entry1.3,entry1.4 
entry2.1,entry2,2,entry2.3,entry2.4 
................................... 

我现在已经在各行的第四个条目。那么,这似乎没有什么大不了的,只需更改我的案例类与第四项(代码气味1),然后更改模式匹配(代码异味2)

有人可以建议我应该如何编写我的代码来处理有了这种情况。我想扩展我的代码而不是修改它。

感谢

+0

如果你想在一个对象中表示你的日志文件,假设你需要在文件改变的时候改变对象。你总是可以将它存储为'List [String]'。 –

+0

不应将文件存储为对象,因为它们将计算进一步向下推进逻辑,因此各行需要表示为对象。我只想知道日志行条目的适当抽象技术,以便我可以适应文件的模式更改,同时保持向后兼容性。我不确定如何将行条目存储为字符串列表可以提供帮助? –

+0

@sc_ray你需要澄清你想用'LogEntry'类做什么。现在我没有看到使用可变长度'List [String]'作为@ bmorris591建议的优势。 –

回答

2

的第一件事,当你想正确抽象的日志行做的是通过名字给各个元素的名称和正确的类型,而不是伪指数(即取值范,ENTRY2等)。因此,我们将有:

case class LogEntry(
    time: java.util.Date, 
    userId: Int, 
    host: String 
) 

打字的严格性取决于你的确切使用情况下(注意,这里host不是java.net.InetAddress)。

当一个新列被添加到您的日志文件,还有,你可能想保留两件事情:

  1. 功能的预期旧式LogEntries
  2. 处理旧的日志文件,即使新功能被添加。

案例1是容易的。只需将字段添加到案例类:

case class LogEntry(
    time: java.util.Date, 
    userId: Int, 
    host: String, 
    port: Int 
) 

既然你的名字,你甚至可以改变字段的顺序和旧代码将仍预计还在这里下地干活了。由于您不想再处理旧的日志文件,只需调整读入的代码即可。

案例2是有一点麻烦:你必须反映事实,你必须在你运行的应用程序的新老日志条目。您可以:

  1. 让其他字段可选,并给予默认值:

    case class LogEntry(
        time: java.util.Date, 
        userId: Int, 
        host: String, 
        port: Option[Int] = None 
    ) 
    
  2. 体现在层次结构的日志格式版本(注:你不应该从案例类继承,所以你必须使正常上课了出来):

    class LogEntry(
        val time: java.util.Date, 
        val userId: Int, 
        val host: String 
    ) 
    
    class ExtendedLogEntry(
        time: java.util.Date, 
        userId: Int, 
        host: String, 
        val port: Int 
    ) extends LogEntry(time, userId, host) 
    

选项1是可以治疗的代码日志条目处理条目类型之间的差异(即,所有功能仍然是LogEntry => ?类型)。进一步还要注意,它可能会允许不一致的日志条目(添加两个字段,两种格式都不存在,格式2需要,您仍然可以将其中一个设置为None)。

选项2让调用代码处理条目类型之间的差异。如果高级功能需要ExtendedLogEntry,则其类型将为ExtendedLogEntry => _,因此您无法向该功能提供LogEntry(可选:模式匹配,并提供默认/回退行为)。此外,它可以防止可能出现的选项1不一致。

关于读入:当读取旧式日志文件时,选项1将自动设置默认参数,在选项2中,旧式日志文件将导致如前所述,LogEntry。所以在这两种情况下,旧的读入代码都不需要改变,但可能适用于检测新式或旧式日志并生成适当的条目。 (请注意,这对于选项2来说可能是一个问题,因为如果您不想投射,通过键入系统可以静态执行日志的样式)。