-
Notifications
You must be signed in to change notification settings - Fork 74
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
Split TaskData
into two separate classes
#696
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to dismiss my review because I certainly lack context in this gem. That being said, I think there's an opportunity to better structure these objects:
The motivation for the refactor
As I understand it, we feel that currently the TaskData
abstraction holds too many responsibilities:
- Defining an API on
TaskData
to be used in the index view - Defining an API on
TaskData
to be used in the show view - Defining the query for
available_tasks
- Defining the query for
find
The current solution
The proposed solution introduces a division of responsibility based on the consuming view. That is, we have a separate abstraction for the index view and a separate abstraction for the show view. Both abstractions define the state and also define the query used to aggregate the relevant task(s).
An alternative solution
To me, it seems there's two responsibilities in question
- Task aggregation (querying
Task
(s)) - Task presentation (decorating a
Task
with helpers for the UI)
If we keep the TaskData
class as is, but remove those class methods that are responsible for querying relevant tasks I think it's responsibility is clear. I see the argument that some methods aren't used by #index
but, in my view, it's up to the UI to determine what it needs to fulfill its role and its reasonable that each view doesn't make use of the entire API.
Then, we can move those query methods #available_tasks
and #find
into their own abstractions. For instance, we can introduce an all new TaskPresenter#index
, TaskPresenter#show
or even separate abstractions for each of the views: TaskIndexPresenter#tasks
, TaskShowPresenter#task
where these methods return a TaskData
instance(s).
Thoughts
I'm curious to hear how you think about this? I'm not sold on the proposed abstractions I presented, but I'm interested in hearing how you're thinking about this separation of responsibility.
Hey @paarthmadan ! Thanks for bringing this up ❤️ To me, the current code is violating the Interface Segregation Principle:
IMHO it's less about Your point on separating querying vs presentation responsibilities is an interesting one! We could split out the querying / aggregating behaviour from the actual object that represents a Does this make sense? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for engaging in the discussion! ❤️
...but to me it would still be fundamental to have TaskPresenter#index and TaskPresenter#show return different objects.
👍 Your rationale makes sense given that it's important to return different objects.
Closes: #675
TaskData
has become a combination of two separate interfaces: one for offering high-level representations of a task on the index page, and one for offering more details info on a specific task on the show page. This PR separates the two roles out into different classes, clarifying the responsibility of each object.I've also dropped the
last_run
alias fromTaskDataIndex
, since these tasks have "related runs" instead of "last runs" with the changes introduced in #667.Open to feedback on naming, I couldn't think of a good way to distinguish the two classes other than the context in which they're used 😅