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.

3 komentarze:

  1. Ja bym zmienił Task na trait lub abstract class a case class użył to stworzenia SingleTask oraz ReccuringTask. Takie podejście powinno uprościć i zwiększyć czytelność kodu w metodzie collectTasks.

    OdpowiedzUsuń
    Odpowiedzi
    1. Postanowiłem wprowadzić swoje rady w życie. Efekty można obejrzeć tutaj (https://github.com/rwieckowski/taskassin). Jako że sam jestem początkujący w Scali ciekawy jestem czy takie podejście ma sens.

      Usuń
  2. Co do jednostek czasowych Scala time (https://github.com/jorgeortiz85/scala-time) wydaje się być idealna.

    Nie spoglądałem w kod, ale pewnie udało by się utworzyć klasę z implicit konwersjami, żeby wyrazić ten sposób kwadrans.

    OdpowiedzUsuń