20 czerwca 2013

Dzień 7 z taskassin - wsparcie dla zadań cyklicznych

Przez ostatnie dni doświadczam powtarzającego się olśnienia użyteczności testów pisanych przed pisaniem kodu produkcyjnego. Pozostawię purystom językowym rozwikłanie zagadki, czy można być oświecanym tym samym zdarzeniem wielokrotnie (bo w końcu raz oświeconym trudno oczekiwać, że można zostać nim ponownie powtórnie przez to samo wydarzenie) i wracam do taskassin, w którym pojawiło się wsparcie dla...powtarzających się...zadań (a niechby to były zadania olśniewające).

I tu pojawia się dylemat młodego (stażem) programisty scalowego - czy, aby nie przeładowuję klasy pl.japila.taskassin.Task nadmiarowymi atrybutami? Dzisiaj dodałem recurring, recurTimes oraz intervalUnits. Czy, aby nie za wiele jak na jedno pojęcie w aplikacji?! Co zasugerujesz młodszemu (stażem)?

Dodatkowym problemem mentalnym jest jednostka czasu, która się pojawia tu i tam. Na razie jest to po prostu Int, ale coś mi mówi, że powinienem już teraz zwrócić uwagę na wyrażenie czasu w bardziej specjalizowany sposób, np. z użyciem faktycznych jednostek czasu jak minuta, godzina, nawet jeśli jedyną byłaby godzina lekcyjna (aka kwadrans). Sugestie rozwiązań wielce pożądane.
case class Task(label: String, due: DateTime, timeUnits: Int = 6,
  recurring: Boolean = false, recurTimes: Int = 0, intervalUnits: Int = 0)

object TaskUtils {

  def collectTasks(ts: List[Task], hours: Int): List[Task] = {
    @tailrec
    def collectTasks(ts: List[Task], accTs: List[Task], remHours: Int): List[Task] = {
      ts match {
        case t :: tail if (remHours >= 0 && remHours - t.timeUnits >= 0) =>
          if (t.recurring) {
            val tt = t.copy(recurTimes = t.recurTimes - 1)
            val tss = tt :: tail
            collectTasks(tss, t :: accTs, remHours - t.timeUnits - t.intervalUnits)
          } else
            collectTasks(tail, t :: accTs, remHours - t.timeUnits)
        case _ => accTs reverse
      }
    }
    collectTasks(ts, Nil, hours)
  }
}
Całość dostępna jako projekt taskassin na GitHubie.