-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TaskSet and func main refactor #41
Comments
An analysis of our current commands yields the following Commands that update state on disk
Commands without side effectsNote that the sync command does change the state of the world, technically. But, from the perspective of the local task database, there are no changes.
|
We might consider a separation of responsibilities like this:
Changes:
func NewTaskSet(repoPath string, opts ...TaskSetOpt) (*TaskSet, error) {
var tso taskSetOpts
for _, opt := range opts {
opt(&tso)
}
// if tso.This or tso.That do stuff
}
type TaskSetOpt func(opts *taskSetOpts)
func WithStatuses(statuses ...string) TaskSetOpt {
return func(opts *taskSetOpts) {
opts.statuses = append(opts.statuses, statuses...)
}
}
type taskSetOpts struct {
statuses []string
renderStrategy string
}
// ResolveTasks gets a list of tasks by id, marks them resolved, and commits the result.
func (ts *TaskSet) ResolveTasks(ids ...int) error { ... }
From case dstask.CMD_RESOLVE:
ts, _ := dstask.NewTaskSet(repoPath, dstask.WithStatuses(dstask.NON_RESOLVED_STATUSES...))
if err := ts.ResolveTasks(cmdLine.IDs...); err != nil {
dstask.ExitFail("aborting: %v", err)
}
// we have been given enough options to know how to render
ts.Render() Advantages of this design:
Disadvantages:
Alternatively, we could opt to keep the new constructor, but not full embrace encapsulating git commits and disk persistence within named methods of
func ResolveTasks(repoPath, cmdLineText string, ids ...int) error {
ts, _ := NewTaskSet(repoPath, dstask.WithStatuses(NON_RESOLVED_STATUSES...))
for _, id := range ids {
task := ts.MustGetByID(id)
task.Status = STATUS_RESOLVED
if cmdLineText != "" {
task.Notes += "\n" + cmdLineText
}
ts.MustUpdateTask(task)
ts.SavePendingChanges()
MustGitCommit("Resolved %s", task)
}
} Advantages:
Disadvantages:
|
Sorry I took so long to review this, struggling to find the time at the moment! Thanks for putting the time into thinking about a refactor, we certainly need one now that we're adding commands and there's some redundancy in the big switch statement. I like the idea of setting a context on taskset, it simplifies things and is similar to the existing filter mechanism. The alternative suggestion was actually exactly what I had in mind myself, adding commands which are implemented as functions, removing the logic from EDIT: Either change would make it easier to use dstask as a library, which would be useful for making an iOS or Android app. We'd have to switch to a go implementation of git -- though I think that would be fairly painless as we're not doing anything too strange. |
I think option number 2 is what I'd advocate, perhaps implemented in two phases. 1) introduce the new constructor for TaskSet, and 2) then move a lot of I might give it a shot this weekend. But before that I'd like to help @ard0gg with testing their PR #37 since I haven't gotten too familiar with the completions code. And it would be good to land that before refactoring out from under them. |
Agreed -- thanks, sounds good! |
I ended up opening #43 for both initial phases, moving much of func main to commands.go and introducing a new constructor for TaskSet. |
@dontlaugh are you happy to close this now, or do you think further work is required? |
@naggie I think we can close this in favor of a new issue around sorting, and the existing issue #12 . I very recently took a look at next steps for folding in more logic into the TaskSet constructor with associated options. I think the "big one" is sorting. In the constructor, we might apply sorting after we've read things from disk with something like: The more I look at it, the more it looks like we're building a query interface to the task database. Given state (in the repo) + some well structured inputs, we should be able to read in and construct a sorted and filtered list of tasks in one go. I'll take on sorting next, since it's on my mind and is an existing feature. I also think it is possible to handle #12 within this design. It is an interesting problem. Time is always a bit tricky. |
A few times now we've hinted at a desire to refactor
func main
. This will involveTaskSet
as well, since manipulating this type is one of main's big jobs right now.We can talk about some possible designs here. We'll want something testable and extensible, if possible. For instance, how might we accommodate #12 and/or #16 ? We don't want to come up with something that makes those awkward to implement.
The text was updated successfully, but these errors were encountered: