Jan 5 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Jan 5 | 4:05 PM |
Aaron | has entered the room |
Mark M. |
hello, Aaron!
|
Mark M. |
how can I help you today?
|
Aaron |
hey Mark!
|
Jan 5 | 4:10 PM |
Aaron |
I don't have any specific questions today. If you are up for it, I would really like it if you could just poke around in my project and see if any problems pop out. I'm interested in feedback at any level of analysis, but I'd say my main concern is identifying any major pieces that are being used incorrectly
|
Mark M. |
OK, got a link?
|
Aaron |
put another way, anything that looks off that you might expect an interviewer to grill me about; better prepare for it
|
Aaron | |
Mark M. |
since this project has a few dozen classes and stuff, is there anything in particular you would like me to look at first?
|
Aaron |
not really, to be honest, in past "code reviews" I've called out specific things, but this time I guess I just want to invert that, and let you look at whatever you think might be interesting to look at
|
Aaron |
I can provide some guidance if needed, but at this point I've addressed most of the things that I know needed work, so I need more open-ended feedback
|
Aaron |
I guess just pretend that I sent this to you as part of a job application
|
Mark M. |
since I haven't hired anyone in ~20 years, that's a bit far-fetched, but I get what you're saying
|
Mark M. |
it's cool that you added the license headers! I'm uncertain if "2018-present" will hold up if it came to some sort of legal throwdown, but that's fairly unlikely anyway
|
Jan 5 | 4:15 PM |
Aaron |
OK, and lol at legal throwdown
|
Aaron |
I copied the headers from the RxJava repo, so if it's good enough for that, it's good enough for me
|
Mark M. |
you have setupStrictMode(); commented out in BaseActivity -- I recommend either using it (e.g., based on a BuildConfig flag) or axing it entirely
|
Aaron |
BuildConfig is a good idea.
|
Mark M. |
// region comments are a cool trick, but personally I find them annoying for smaller files -- I recommend using them only if they will materially help navigation within the source (so, for example, BaseActivity doesn't really need them IMHO)
|
Aaron |
OK true
|
Mark M. |
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- you have "activity" in the error message, but this is the fragment one (copy/paste error, I'm guessing)
|
Aaron |
yep
|
Mark M. |
in NoSurfApplication, you have initLeakCanary() commented out -- so, same thing as with setupStrictMode() (use it or nuke it)
|
Jan 5 | 4:20 PM |
Aaron |
I think LeakCanary can actually be left in release builds, IIRC they somehow replace all of the classes/methods with empty stubs, I'll double check that
|
Mark M. |
there are two separate dependencies, one you use with debugImplmentation and the other with releaseImplementation
|
Aaron |
left *enabled
|
Mark M. |
that allows you to keep your LeakCanary configuration code alone, and it just no-ops on a release build
|
Aaron |
ah yeah, that's right
|
Aaron |
yeah I'll make sure that's set up right.
|
Mark M. |
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- code comments are for "future you" and team members, and I would expect all of them to know the things that you commented on
|
Mark M. |
code comments are great, but at the same time, you don't want to come across as "talking down" to the reader of those comments
|
Aaron |
yeah, I understand, those were actually there for my own benefit but I get your point, I'll pull them out and keep that information in my private notes
|
Aaron |
there are likely more comments like that, I'll fix them
|
Jan 5 | 4:25 PM |
Mark M. |
another possibility for that role is to add "note to self:" or something as a prefix
|
Aaron |
true
|
Mark M. |
in that same file, deleteAllClickedPostIds() is marked with @SuppressWarnings("unused") -- is that really unused?
|
Aaron |
I have had some problems with Lint reporting stuff as unused that is actually used. As far as I can tell it's bugs in Lint. I added the annotations just to make it stop, not sure if that's wise though
|
Mark M. |
hmmm... OK, that might be worth an explanatory comment, if the problem still exists
|
Aaron |
it's possible I'm just not understanding something about how Lint works though, i'm somewhat, but not super sure about it being bugs
|
Aaron |
ok
|
Mark M. |
similarly, on ClickedPostIdRoomDatabase, you have @SuppressWarnings("ALL") -- that's kinda scary, so if you're sure you want that, a comment justifying the decision might be a good idea
|
Aaron |
OK
|
Aaron |
I'll try deleting all the annotations and re-running the inspections and take another look
|
Aaron |
things may have changed anyway since I added them, and in any case, I'll comment them this time
|
Mark M. |
another commented out bit: addCallback(clickedPostIdRoomDatabaseCallback) in your RoomDatabase.Builder setup
|
Jan 5 | 4:30 PM |
Mark M. |
part of the reason why I mention this commented-out code is that in a big app, unused code is just stuff that gets in the way of things like refactoring, and so people might be sensitive to having unused code lying around a small project like this
|
Aaron |
OK, that piece in particular I left there because I thought I might want to use it, but I get it, I'll either comment it or remove it
|
Aaron |
sounds like removing it is preferred
|
Mark M. |
yeah, up until you want to start showing the code to others, having stuff around like that is perfectly reasonable
|
Aaron |
roger that, yeah I guess adding comments isn't going to help get it out of the way.
|
Mark M. |
and keeping that stuff on a private git branch is also a possibilty
|
Mark M. |
also in your RoomDatabase.Builder setup, since you're still on schema version 1, fallbackToDestructiveMigration() shouldn't be needed
|
Aaron |
I need to spend a few days learning more git, I actually think I'm going to get roasted about that in interviews, as my commit history is just linear commits to master with nothing else, not so ideal
|
Aaron |
OK
|
Mark M. |
eh, for a small single-developer project like this, not using an elaborate branching strategy is reasonable
|
Mark M. |
being honest about your level of git skills is appropriate, but you don't have to show *everything* off in this repo
|
Aaron |
ah, well, good lol
|
Mark M. |
you seem to go back and forth between using constants for strings or using them inline, such as the "clicked_post_id_database" parameter in your RoomDatabase.Builder
|
Aaron |
ah, that's an oversight, I meant to extract them all out, will fix it
|
Mark M. |
you can do what you want, but I recommend an identifiable pattern and one that you're willing to defend
|
Jan 5 | 4:35 PM |
Aaron |
yes, good catch
|
Mark M. |
"always defined as constants" or "always defined as constants if referred to 2+ times" are good identifiable patterns
|
Aaron |
I like the former
|
Mark M. |
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- you have an interface to isolate the implementation details, but then you leak an implementation detail in the form of SharedPreferences.OnSharedPreferenceChangeListener
|
Mark M. |
*technically*, you can use that listener for things that are not SharedPreferences, but that'd be weird
|
Aaron |
ok, so you're saying I should make some kind of custom listener class that just wraps SharedPreferences.OnSharedPreferenceChangeListener?
|
Aaron |
and use that instead?
|
Mark M. |
ideally, yes
|
Aaron |
OK
|
Aaron |
got it
|
Aaron |
makese sense
|
Mark M. |
actually, it's more that SettingsStore would have its own listener interface (e.g., SettingsStore.Listener)
|
Mark M. |
your clients would implement that interface instead of OnSharedPreferenceChangeListener
|
Aaron |
ah, yes, that would align with SharedPreferences having its listener, sounds good
|
Mark M. |
and listeners are usually interfaces (or abstract classes)
|
Jan 5 | 4:40 PM |
Mark M. |
SettingsStore has no setters -- when do these values get changed?
|
Aaron |
tbh there are a lot of places in this app where I could abstract more, like my repository just exposes retrofit calls, it doesn't try to wrap that in any API of its own, but i'm just accepting that since I am never going to replace retrofit, and that's what I'll tell interviewers if they ask
|
Mark M. |
OK
|
Aaron |
er, I'm not sure why those variables are even in the interface there
|
Aaron |
I should probably have setters and getters in the interface and NOT the variables
|
Aaron |
I think, at least
|
Mark M. |
I'm not sure what you're referring to precisely -- I just don't see where your preferences get updated
|
Aaron |
there is a preference fragment
|
Mark M. |
ah
|
Aaron |
a settings screen
|
Aaron |
yeah
|
Mark M. |
in that case, I would recommend just getting rid of SettingsStore
|
Mark M. |
you're kinda locked into SharedPreferences as the data storage vehicle, so the abstraction isn't buying you anything
|
Jan 5 | 4:45 PM |
Mark M. |
keep PreferenceSettingsStore, and have clients use it, just without the interface
|
Aaron |
yeah, I had included it more just to show an example of abstraction, but that might be counterproductive if there's not a reason for doing so
|
Aaron |
and what I was referring to regarding the variables, it's my understanding that you only really include variables in an interface if you want to have constants
|
Mark M. |
um, you lost me there, but, that's OK
|
Aaron |
lol ok, I'll brush up on that
|
Mark M. |
looking at RateLimitInterceptor, you have another couple of strings not as constants
|
Mark M. |
also, just to confirm: the Reddit rate-limit is per-client (i.e, per-user), not per-app, right?
|
Aaron |
correct
|
Mark M. |
that's rather nice of them
|
Mark M. |
a lot of these rate limits are per-app, which makes client-side use troublesome if you get popular
|
Aaron |
I had to actually dig to figure that out, I had the same question and it wasn't clear in their docs
|
Aaron |
but yes
|
Jan 5 | 4:50 PM |
Mark M. |
also in RateLimitInterceptor, you should be able to avoid the division, and hence the division-by-zero scenario
|
Mark M. |
you have int requestRatePerSecondDuringThisPeriod = xRateLimitUsed / (600 - xRateLimitReset);
|
Mark M. |
and you have if (requestRatePerSecondDuringThisPeriod >= 1)
|
Mark M. |
which means that you are comparing xRateLimitUsed / (600 - xRateLimitReset) >= 1
|
Mark M. |
which is equivalent to xRateLimitUsed >= 600 - xRateLimitReset (multiplying both sides by 600 - xRateLimitReset)
|
Aaron |
math is hard
|
Aaron |
I'll fix it
|
Mark M. |
if you can avoid the division in your algorithm, it's probably a good thing
|
Aaron |
agree
|
Mark M. |
having a Thread.sleep() in the interceptor is kinda icky, though I agree that it is a convenient solution
|
Aaron |
I don't have tests for that class and I only noticed the division by zero when it happened to occur
|
Aaron |
thanks so much for all of this, for the last few minutes of the chat can you tell me what you think about this:
|
Aaron |
pretty open ended and subjective but nevertheless
|
Aaron |
I'm going to address all of this, and some feedback I've gotten from other people, but I'm mostly switching over to job seeking mode, although I want to keep working on code or I'm going to start forgetting stuff, so my plan is
|
Jan 5 | 4:55 PM |
Aaron |
to start working through one of Google's sample apps, either the I/O app or Sunflower
|
Aaron |
I think that would be a really good next step, as I should have enough baseline knowledge now to make sense of those
|
Aaron |
seem like a reasonable plan to you? like I said I know it's subjective
|
Mark M. |
¯\_(ツ)_/¯
|
Aaron |
lol yeah
|
Aaron |
fair enough
|
Mark M. |
I mean, I tend to be more tactical when reviewing other apps
|
Mark M. |
but that's me, and I know lots of people like to sit down and tear through an app like those to see stuff
|
Aaron |
yeah, my feeling is just that it would 1) be good to get practice absorbing other people's code, and 2) these Jetpack demo apps use lots of the same stuff I used, except probably more correctly, so I can learn from that
|
Mark M. |
that's all reasonable
|
Aaron |
anyway yeah, that's what I'm going to do, mainly just wanted to see if that generated any particularly storng response from you, but sounds like it's reasonable, exactly
|
Aaron |
cool
|
Aaron |
alright, that's awesome, thanks so much for your help today
|
Mark M. |
you're welcome!
|
Aaron |
I'll probably still pop in with some questions in the next few weeks, but not nearly as heavily as I have been
|
Aaron |
enjoy the rest of the weekend, talk later
|
Mark M. |
that sounds fine
|
Mark M. |
see ya!
|
Jan 5 | 5:00 PM |
Aaron | has left the room |
Mark M. | turned off guest access |