Feb. 20th, 2012

juan_gandhi: (Default)
Обычное дело, нарисует человек кучу тестов, а они не идут, NPE бросается из середины кода. Вместо того, чтобы лечить код, человек начинает соображать, а, это у меня в окружении такая-то переменная не проинициализирована, щас её проинициализирую, и тест пройдёт, и значит всё хорошо.

Менталитета...
juan_gandhi: (Default)
А любопытно устроен менталитет программистов - если чего не хватает, типа файл не найден, то это всё считается чьи-то ошибки. Кругом ошибки, и если программа валится по npe, а корневая причина отсутствие какого-нибудь файла по предполагаемому пути, то это "ошибка". Сегодня за обедом с архитектором беседую, говорю, слышь, ты тут класс написал, "декорированный брокер", у него есть делегат, которого ты называешь _decorated, и ты нигде вообще не проверяешь что он null, не null, а делегируешь себе - это типа as designed? На что он ответствует - ну npe будет если только система неправильно сконфигурирована, тогда вообще сервер должен завершать работу.

Он, конечно, ни хера работу не завершает, а хуярит и хуярит, извините за выражение, исключение за исключением.

И я не думаю, что мы с ним когда-нибудь договоримся.

Но меня что-то нынче пробило писать примерно вот так:

  def existingFile(file: File) = {
    require(file.exists(), "File " + file.getAbsolutePath + " must exist")
    file
  }

  def existingFile(path: String) = existingFile(new File(path))

  def existingFile(folder: File, name: String) =  existingFile(new File(existingFile(folder), name))



Да затрахало елозить с юниттестами да дебагерами. Кусок кода может сам признаться, чего ему не хватает, сразу, а не после трагических ошибок.

P.S. Надеюсь вы понимаете, что этот дешевый приёмчик есть замена правильному решению
class ExistingFile(File file)...
juan_gandhi: (Default)
object FS {
  class TextFile(val file: File) {
    def text = Source.fromFile(file).mkString

    def text_=(s: String) {
      val out = new PrintWriter(file, "UTF-8")
      try{ out.print(s) } finally{ out.close }
    }

    def parent = new Folder(file.getParentFile)
    override def toString = file.getAbsolutePath
  }

  class ExistingFile(file: File) extends TextFile(file) {
    require(file.exists(), "File " + file.getAbsolutePath + " must exist")
  }

  class Folder(path: File) extends ExistingFile(path) {
    require(path.isDirectory, "File " + path.getAbsolutePath + " must be a directory")
    def file(name: String) = new TextFile(new File(path, name))
    def subfolder(name: String) = new Folder(file(name))
    def existingFile(name: String) = new ExistingFile(file(name))
  }

  implicit def asFile(file: TextFile) = file.file
  implicit def textFile(file: File) = new TextFile(file)
  implicit def existingFile(file: File) = new ExistingFile(file)
  implicit def asFolder(file: File) = new Folder(file)
  implicit def file(name: String) = new File(name)

}


and the usage is:

  val configFiles = List("ac_office.xml", "broker.xml", "dse.xml", "pe.xml", "ao_office.xml", "dashboard.xml", "license.txt"")
  for (name <- configFiles) {
    val d = bootDir.file(name)
    if (!d.exists) d.text = setupDir.subfolder("setup").existingFile(name).text
  }

juan_gandhi: (Default)
ну блин, это ж другая жизнь пошла! Сразу всё ясно, что где почём и почему.

org.specs.runner.SpecError: java.lang.IllegalArgumentException: requirement failed: File /Users/vlad/iongrid/sw/server/package/monolith/target/boot/dashboard.xml must exist
juan_gandhi: (Default)
У вас лаптоп на коленях, интернет быстрый, андроид или айпод в кармане... но вот 20 баксов в год на жж ну совершенно нету!

Забавно, да?

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

August 2025

S M T W T F S
      12
3456789
10 11 12 13141516
171819 20212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 23rd, 2025 09:18 am
Powered by Dreamwidth Studios