Mark M. | has entered the room |
Dec 29 | 7:25 PM |
Mark M. | turned on guest access |
Dec 29 | 7:35 PM |
Aaron | has entered the room |
Mark M. |
hello, Aaron!
|
Mark M. |
how can I help you today?
|
Aaron |
hello, Mark, I have 3 miscellaneous questions today, here they are:
|
Aaron |
View paste
|
Dec 29 | 7:40 PM |
Mark M. |
whew, I was afraid you were going to ask how Notre Dame might stage a comeback against Clemson...
|
Aaron |
LOL
|
Mark M. |
regarding #1, PostsAdapter is used in a RecyclerView that is shown by PostsFragment, right?
|
Aaron |
exactly
|
Mark M. |
if so, then it's reasonable for PostsAdapter to have a reference to its hosting fragment
|
Aaron |
I see
|
Mark M. |
if you wanted, you could pass in more focused things, like a LayoutInflater and Lifecycle
|
Mark M. |
and whatever settingsStore is
|
Mark M. |
those are the three things that you are using on PostsFragment
|
Aaron |
yeah, those are the objects I was saying I could pass in through the constructor, exactly
|
Mark M. |
or, you could say that PostsAdapter takes in a PostsAdapterHost parameter, where that is an interface that PostsFragment implements and exposes those three methods that you're calling
|
Aaron |
OK, that also makes sense
|
Mark M. |
either of those approaches would isolate PostsAdapter from the detail of *exactly* what's hosting it
|
Mark M. |
that becomes important if the adapter might be used in multiple places, but it can be a bit of YAGNI if there are no plans to have another host
|
Dec 29 | 7:45 PM |
Aaron |
yes, unlikely
|
Mark M. |
regarding #2, my Dagger-fu is weak, so I can't really provide advice for that, sorry
|
Aaron |
how about line 131? that call inserts a record into Room, that's the only thing I am using the ViewModel reference for that can't be replaced by passing things into the constructor
|
Aaron |
is it reasonable to reference the VM from the adapter?
|
Aaron |
would it be...nicer...to put the method in the host fragment and just call it through that?
|
Mark M. |
AFAIK, you're not aiming to follow some specific GUI architecture here (MVC, MVP, MVVM, MVI, etc.)
|
Aaron |
yes, I am, MVVM
|
Mark M. |
what are you considering your presenter to be? MVVM, despite the name, still usually has some sort of presenter/controller element
|
Mark M. |
s/usually/often
|
Aaron |
I can't really answer that. I kind of understand the role of a presenter in MVP but TBH that's new info to me that there should be a presenter in MVVM
|
Dec 29 | 7:50 PM |
Mark M. |
then, kinda by default, you're lumping that role into the view, which isn't unreasonable
|
Mark M. |
particularly for a smaller app
|
Mark M. |
in which case, I usually think of a RecyclerView.Adapter and similar things to be simply an extension of the activity/fragment
|
Mark M. |
and that's serving as your view
|
Mark M. |
so, it seems reasonable for the adapter to have a reference to the viewmodel
|
Mark M. |
if you want to isolate all viewmodel interactions to the hosting fragment, that's fine, but I'm not sure it's buying you a lot
|
Mark M. |
this is where MV* starts to become soup
|
Aaron |
I guess the way I am thinking of it, the activity/fragments are performing the role of controller as well as the view
|
Mark M. |
and it's why I try to generally steer clear of GUI architecture debates :-)
|
Mark M. |
right
|
Aaron |
I'm not super sure how "Presenter" would fit into that
|
Mark M. |
don't worry about it
|
Aaron |
lol, yeah, I'm sure it will become clearer as I get more experience, fair enough
|
Mark M. |
if anything, IMHO, it'll get murkier, as your experience will differ from everyone else's
|
Dec 29 | 7:55 PM |
Aaron |
heh, or that
|
Mark M. |
while we try to talk a good game about these things being formal GUI architectures, if you ask six developers to define MVVM, you might get six different answers
|
Aaron |
yes, I have noticed that
|
Mark M. |
that's one of the reasons why I try not to get hung up on that aspect of app architecture
|
Mark M. |
having clean separations between the UI and backend concerns (e.g., repository pattern) are easier to get agreement on
|
Mark M. |
everything else, on a team project, I'll usually let others decide, as usually they care way more than I do
|
Mark M. |
regarding #3, in many cases, it depends on what the problem is and where you detect it
|
Mark M. |
if you are in position to handle it without an exception, that's generally a good thing
|
Mark M. |
OTOH, sometimes you can't -- you try to read in the file and it is corrupt, for example
|
Mark M. |
or you make the Web service request and Reddit is having a bad day and returns a 500
|
Mark M. |
or stuff like that
|
Mark M. |
in the case of the Reddit 500, the exception would be thrown by OkHttp/Retrofit, and so long as you're handling it properly, life is fine
|
Dec 29 | 8:00 PM |
Mark M. |
in the case of the corrupt data, though, your own code may be the one that is defining "good" versus "corrupt", and so you may need to throw your own exception to say "halp!"
|
Mark M. |
by the time the problem gets to the GUI, we need it to no longer be an exception, because we don't want the app to crash
|
Mark M. |
but it may be that the simplest way for code deep in a repository to point out a problem is to throw an exception
|
Mark M. |
you're probably already dealing with other exceptions (the Reddit 500 response, FileNotFoundException, etc.)
|
Mark M. |
so adding another one just adds to an existing communications channel
|
Mark M. |
in an app, that's the sort of scenario where I see manual exceptions being thrown
|
Mark M. |
libraries might use exceptions as part of their API, particularly custom exceptions, and so they're a different beast
|
Aaron |
right, so, I'm comfortable enough with handling exceptions thrown by other code, that's not my issue, the issue is identifying scenarios when I should throw them manually, for example:
|
Aaron | |
Aaron |
line 139
|
Mark M. |
onNewIntent()?
|
Aaron |
this function handles a new intent when the user logs in, yes
|
Aaron |
(typing)
|
Dec 29 | 8:05 PM |
Mark M. |
onNewIntent(), being a framework callback method, is not the sort of place you want to be throwing an eception
|
Mark M. |
er, exception
|
Aaron |
the intent contains a code from the Reddit API that is used to log the user in
|
Mark M. |
all that will do is crash the app
|
Mark M. |
or are you referring to the exceptions that you're catching there?
|
Aaron |
my extractCodeFromIntent() method throws a couple different exceptions, depending on whether there is a valid code or not
|
Aaron |
yes
|
Aaron |
but thing is, I could just as easily accomplish the same thing without throwing any exceptions
|
Mark M. |
right
|
Aaron |
I could just use some if/else logic to see whether the code is valid
|
Mark M. |
how complicated is extractCodeFromIntent()?
|
Aaron |
that's just one example of a place where I am not sure whether I should be using exceptions, or just if/else
|
Aaron |
not complicated
|
Mark M. |
that's not a place where I would use a custom exception, off the cuff
|
Aaron | |
Mark M. |
extractCodeFromIntent() is basically a utility function
|
Mark M. |
IMHO, it should just be returning some sort of result, both for success and failure scenarios
|
Mark M. |
but, if you had a similar algorithm that needed to operate on a Web service response, so you're deep inside a repository, then an exception might be reasonable
|
Mark M. |
it's not the algorithm so much as it is where it is being used
|
Dec 29 | 8:10 PM |
Mark M. |
my question about the complexity was trying to figure out if the exceptions were being thrown several layers deep
|
Mark M. |
and in this case, they're not
|
Mark M. |
there's no particular *harm* in throwing an exception, so long as you're really sure that you're going to handle it
|
Aaron |
thinking
|
Mark M. |
to draw an analogy, throwing an exception is like lighting the fuse on the cartoon stick of dynamite, then handing the dynamite to a befuddled coyote, then dashing off -- so long as the coyote can do something useful with that dynamite, it's OK
|
Mark M. |
if, OTOH, all the dynamite is going to do is blow up in the coyote's face, well, that's not very nice :-)
|
Mark M. |
and so the tendency is to throw exceptions when better alternatives either do not exist or would require tons o' work
|
Mark M. |
in your case, extractCodeFromIntent() has a simpler, less-explosive alternative
|
Mark M. |
(NOTE: no actual coyotes were harmed in the creation of this chat)
|
Aaron |
lol, I do appreciate the cartoon analogy though, that is firmly on my level :p
|
Aaron |
let me pose this another way
|
Dec 29 | 8:15 PM |
Aaron |
returning to this: "you try to read in the file and it is corrupt, for example"
|
Mark M. |
not sure what you want me to say about the corrupt-file scenario
|
Dec 29 | 8:20 PM |
Aaron |
sorry, I lost my internet connection
|
Aaron |
what was the last message received?
|
Mark M. |
you wrote: eturning to this: "you try to read in the file and it is corrupt, for example"
|
Mark M. |
(give or take an "r")
|
Aaron |
yeah, sorry, I am home for the holidays and my parents installed a bunch of smart devices, I think the house is now a Russian botnet
|
Aaron |
here is what I tried to send
|
Aaron |
View paste
|
Mark M. |
well, you're not likely to be reading a file in one function deep from a framework GUI callback
|
Mark M. |
my corrupt-file scenario is for a case where you have some code, buried in a repository, that runs into a problem
|
Aaron |
hmm, so is the point, throwing exceptions is more about transferring the program control flow to somewhere else, and less about the complexity of the error?
|
Mark M. |
that's a reasonable description
|
Aaron |
hmm, OK, I need to think about that, it might be the missing piece that makes it click
|
Dec 29 | 8:25 PM |
Aaron |
alright, I will let you go a whole 5 minutes early, thanks as always for your help, no more questions at this time
|
Mark M. |
OK
|
Aaron |
have a good new year!
|
Mark M. |
chats next week are also on an altered schedule, due to the holidays
|
Mark M. |
you too!
|
Aaron |
no problem, good night
|
Aaron | has left the room |
Mark M. | turned off guest access |