Office Hours — Today, January 3

Saturday, December 29, 2018

Jan 3
7:20 PM
Mark M.
has entered the room
7:25 PM
Mark M.
turned on guest access
ryan7
has entered the room
Mark M.
hello, ryan7
how can I help you today?
ryan7
Hi Mark!
7:30 PM
ryan7
Long message I pretyped, just a warning
View paste
Hi Mark!
New subscriber here! Before I ask my question I just wanted to thank you for the tremendous value you've provided. No where else can you get such quality and depth of information for a mere $20. Personally I think the subscription should be $20 PER month(I would gladly pay that for what you're providing here). 

I'm a new college grad seeking an Android developer job in Los Angeles, CA. I would like to employed asap, but shooting to build projects for 3 more months. I just wanted to check that I was on the right track.

Q1. In your opinion what are the essential skills/libraries(either android framework or general software engineering) to landing a junior position OR what libraries do you think a "good enough to impress" android project would contain?

My answer: MVP or MVVM, Dagger 2, Data persistence, Fragments, Material design theme, Retrofit, Junit/Expresso Testing. This is from me building a simple project then realizing, "that's bad practice, I need an another library to solve this/make it easier."

Q2. Is there any MVP best practices articles you would recommend? Since it's not officially supported by Google, not sure which articles are actually good Software engine
...
Mark M.
first, thanks for the kind words!
in terms of Q1, that's a pretty decent list
I'd generalize MVP/MVVM to "some GUI architecture"
we "talk a good game" in Android development about MVC, MVP, MVVM, MVI, etc., but in reality, we tend to wind up with MVS (Model-View-SomethingOrAnother)
ryan7
No problem! I find myself comparing the books you've created to other paid resources (Big nerd ranch, Professional android) and yours almost always seems to be more up to date and have better prose.
Mark M.
"up to date" is what I aim for, though the past year has been a bit rough on that front
back to Q1: for example, I wouldn't sweat "should I demonstrate MVP vs. MVVM?" -- pick what you're comfortable with, and be able to explain your choice in an interview
ryan7
Well that's understandable, the past 2 years google has put out so much new stuff.
7:35 PM
ryan7
Ok, yea I was just starting off with MVP, then seeing the pros/cons firsthand
Mark M.
learning what you like and dislike, and being able to explain them, should be more valuable than the actual bits and bytes of your demo code
after all, it's reasonably likely that you'll be joining a project with an existing code base, as opposed to one that is starting from scratch
so you'll need to adapt to whatever GUI architecture they're using, and that implies that you understand the *why* of your MV* choice more than the mechanics of its implementation
in terms of other stuff for Q1: have Kotlin on your short list, along with some image loading library (Glide, Picasso, etc.)
similarly, have something reactive on your short list: LiveData, RxJava, or perhaps Kotlin coroutines
View paste
particularly if you go the Kotlin route, I'd generalize "Dagger 2" to "some dependency injection solution" -- Koin, for example, is quite a bit simpler than Dagger IMHO
7:40 PM
Mark M.
but if you hit your list, you'll be doing pretty good
note that I haven't been hiring junior developers, or been keeping tabs on expectations for them
and, of course, the technologies we have discussed are for kinda "standard fare" apps -- in LA, if you want to do more media stuff, spend time with ExoPlayer
Aaron
has entered the room
Mark M.
similarly, games are a whole 'nuther ball of wax
ryan7
Thanks Mark!
Mark M.
(BTW, hello Aaron -- I will be with you shortly!)
Aaron
hello Mark, take your time
ryan7
Unfortunately I have to take off, but thanks for your very detailed answers
ryan7
has left the room
Mark M.
ryan7: in terms of Q2, I specifically try not to provide a lot of advice for GUI architectures anyway
OK... Aaron, how can I help you today?
Aaron
so, my app is getting pretty close to a "finished" state, at least as finished as I am planning to make it, I've mostly been focused on learning some basic Kotlin and unit testing this last week, and I have a few open-ended questions today mostly related to those
here they are:
View paste (2 more lines)
1. Can you take a look at a couple classes I've converted to Kotlin, and let me know if you spot anything that can be done more idiomatically? Did my best to apply everything I learned in your book, but it was a lot of info to take in all at once.

https://github.com/ajh3/NoSurfForReddit/blob/master/app/src/main/java/com/aaronhalbert/nosurfforreddit/ui/main/MainActivity.kt

https://github.com/ajh3/NoSurfForReddit/blob/master/app/src/main/java/com/aaronhalbert/nosurfforreddit/utils/SplashHelper.kt

2. I wrote my first two unit tests (also in Kotlin, and obviously post-facto as I was not doing TDD during this project). Am I on the right track here, or does anything look off/problematic?

https://github.com/ajh3/NoSurfForReddit/blob/master/app/src/test/java/com/aaronhalbert/nosurfforreddit/data/repository/AuthenticatorUtilsTest.kt

https://github.com/ajh3/NoSurfForReddit/blob/master/app/src/test/java/com/aaronhalbert/nosurfforreddit/data/repository/RepoUtilsTest.kt

3. When we talk about MVX GUI architectures in the context of an overall clean architecture, is it correct to think about them as "sub-architectures" which apply only to the Presentation layer?

4. I reorganized the packag
...
mostly just looking for sanity checks/feedback on things I don't know that I don't know that I don't know
:D
7:45 PM
Mark M.
in terms of #3, I would describe MV* and clean architecture as related but orthogonal
depending on your implementation, MV* might get a bit more into clean architecture beyond the presentation layer
IMHO, though, that's an architecture smell
for example, clean architecture really calls for true POJO/POKO classes as your model objects
and so things like Retrofit responses and Room entities would not count and would be treated more as data transfer objects (DTOs)
however, a lot of apps don't bother with that sort of separation
I guess I would phrase it as: in a code base adhering pretty strongly to clean architecture, I would expect MV* to affect the presentation layer mostly
bearing in mind that I don't claim to be an expert on clean architecture, or on MV* for that matter
Aaron
ok, that is pretty much what I've gathered, so that's a good enough answer for me
7:50 PM
Mark M.
in terms of #4, your util package has a bit more in it than I'd like, compared to the overall number of classes in the project
util tends to wind up as a "junk drawer", and so I try to minimize what goes in one
Aaron
yep, I'd say that's pretty much what it is
any particular suggestions on how to split it up?
Mark M.
one way of minimizing that is to have more than one utils package, where you have a bunch of stuff that is tied more closely to one layer
so, for example, in addition to the top-level utils, you could have ui.utils
where data binding, WebView, and other UI-ish stuff might go
Aaron
ah yes, that seems reasonable
Mark M.
in your case, I suspect that most of that stuff would wind up in ui.utils, which means it didn't improve today's code that much
however, it might help as the project grows
and, as you find a few classes with commonality, you can move them to peer subpackages under ui
7:55 PM
Mark M.
top-level utils packages tend to be the junkiest of junk drawers; having a few smaller such packages tied to specific areas at least categorizes the junk
7:55 PM
Aaron
makes sense, I'll do that
Mark M.
anything else before I start firing off code review comments for the classes you have in #1 and #2?
Aaron
nope, go ahead
Mark M.
note that I'm only reviewing from the GitHub repo, not from an IDE, so I'll be adding some weasel words to my comments :-)
for example...
if those are only used by this class, make them private
(from GitHub, it's a pain for me to tell if they're being used elsewhere)
Aaron
got it, no problem
Mark M.
since Kotlin makes its equivalent of anonymous inner classes even easier than in Java, you might consider whether the activity should implement OnSharedPreferenceChangeListener, or should it hold an object that does
Aaron
talking about object expressions?
Mark M.
yes
IIRC, OnSharedPreferenceChangeListener follows the single abstract method (SAM) pattern
8:00 PM
Mark M.
so you can just use a lambda
val listener = SharedPreferences.OnSharedPreferenceChangeListener { key -> TODO() }
Aaron
OK, will look into it
Mark M.
prefer val to var -- immutability is your friend
in this case, I think you only ever assign a value here in the declaration
Aaron
yep, correct, that's a mistake
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- not really Kotlin-related, but the comment's explanation is kinda scary
stuff before super.onCreate() is worrisome and should be minimized where possible
Dagger notoriously needs it, so that's fine
but if there's a way you can change pickDayNightMode() so it can be after super.onCreate(), you'll have an easier time with code reviewers :-)
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- if you wanted, you should be able to replace the get() with [] notation -- ViewModelProviders .of(this, viewModelFactory)[MainActivityViewModel::class.java]
8:05 PM
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- I'm old-school and would rather see an if here (I reserve Elvis for assignments and stuff)
Aaron
OK
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- if you haven't done so, consider setting up Android Studio's Kotlin code formatting rules to the Kotlin standard in Settings, then reformat your code
IIRC, in standard Kotlin formatting, that closing parenthesis would go on the next line
Aaron
OK
Mark M.
overall, the Kotlin community is trying to be a bit more anal about code formatting than we saw with previous-generation languages (e.g., Java), which is why I mention it
Aaron
yes, good call
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- you can change that to if (code.isEmpty())
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- not Kotlin-specific, but I'm old-school and would rather see an else than a mid-function return, particularly for something this small
8:10 PM
Mark M.
nothing in SplashHelper leaps out at me, other than code formatting
one top-level comment: you should consider adding copyright/license headers to these files
skipping them for XML and stuff is OK, but for program code, it's good licensing form to have the license boilerplate on the files
Aaron
I see, alright
is there a way in Android Studio to programmatically add that to all my files at once?
Mark M.
not that I know of, but I haven't looked for it either
Aaron
ok no worries
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- I assume "sut" is "system under test"; if so, consider "underTest" as a more readable property name
Aaron
OK
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- if it's the same for each test, you could make the property a val and initialize it there, allowing you to skip the @Before function
8:15 PM
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- are you sure that you want that client ID in the git repo? I don't know much about Reddit's API and terms/conditions
Aaron
yes, it's OK
Mark M.
you still might consider at least pulling it out of the Kotlin source, such as having it in gradle.properties and from there add it to BuildConfig
Aaron
well,
Mark M.
I assume that client ID is used elsewhere, so you should aim to define it only once
Aaron
it is in my BuildConfig and that's where I'm getting it from in the production classes (along with several of the other variables that get built into that URL), what I was attempting to do in the test, is to provide assurance that if any of those variables accidentally get changed, the test will tell me
Mark M.
ah
that's reasonable, though you might want to add some comments to that effect, to help future you
Aaron
as per that comment, that test isn't actually testing any logic of my own, it's just basically verifying the pieces of that URL
line 29 has the comment - does it not make sense?
Mark M.
if it makes sense to future you, that's what matters
I didn't interpret that as "the API key might have changed"
Aaron
lol alright
Mark M.
but, I don't know all of what is going in those URLs
Aaron
ok, understood
Mark M.
a general comment about the unit tests: unlike instrumented tests, we can use backtick function names with unit tests
8:20 PM
Mark M.
so, instead of this_tests_stuff(), you can use `this tests stuff`()
you like fairly verbose test function names, and so being able to use whitespace may help with readability, both for the code and for the test output
Aaron
ah yeah I read about that, I'll change it to take advantage
Mark M.
unfortunately, something about AndroidJUnitRunner means we can't do that for instrumented tests
Aaron
that reminds me of a question that came up in the BCG, actually
Mark M.
https://github.com/ajh3/NoSurfForReddit/blob/ma... -- your test libraries may already have an assertEmpty() or similar function
Aaron
ah yes definitely
Kent S.
has entered the room
Mark M.
or, since you seem to have Hamcrest, it'll have something for empty strings
Aaron
(sidebar, p.1030, second to last paragraph of BCG, "You cannot package JUnit tests..." -> isn't that exactly what AndroidJUnitRunner does, lets you run instrumented unit tests on the actual device?)
Mark M.
sorry, I'll need to look at that later
Aaron
no problem
Mark M.
let me take a question from Kent, since the chat is nearly over, and I'll return to you shortly
Kent: hi! do you have a question?
Aaron
sounds good
Kent S.
hi Mark, I wanted to thank you for updating with Kotlin
Mark M.
it'll be a sloooooooooooooooow process
but, you're welcome!
Kent S.
Your Java versions have been invaluable, I won't waste any of your time. Thank you for what you do :)
8:25 PM
Mark M.
thanks for the kind words!
Kent S.
have a good night.
Kent S.
has left the room
Mark M.
OK, back to the review...
overall, with your unit tests, other than what I mentioned above, I don't have any comments
Aaron
alright, that's good
Mark M.
I haven't used that particular Kotlin-over-Mockito library, so I'm not really able to comment on how you're using it
Aaron
np
Mark M.
note that you if want Hamcrest and Kotlin, there is Hamkrest
not saying that you have to use it; just making sure you knew it existed
Aaron
ok, haven't come across that yet, I'll take a look
Mark M.
it's just a Hamcrest variant that is more Kotlin-native
Aaron
alright, sounds good, well that was a lot of good info today, thanks for that
Mark M.
with regards to the paragraph, I'm not sure what your question is
instrumentation testing requires a development machine
some developers have looked to have a way to exploit instrumentation APIs from a device-installed APK, which isn't possible
Aaron
next time I might ask you to just poke around in the codebase in general with no specific questions, just to see if any macro-level problems pop out, but we definitely don't have to spend a whole hour on it, I really appreciate all the help but I don't want to continue using the chats so heavily
8:30 PM
Mark M.
so long as there aren't others here, you're welcome to the chat time
Aaron
thanks :)
Mark M.
and that's a wrap for today's chat
the next one is tomorrow at 9am US Eastern, part of the scrambled holiday schedule
Aaron
sounds good, talk later
won't be there for that, maybe the day after
night
Aaron
has left the room
Mark M.
turned off guest access

Saturday, December 29, 2018

 

Office Hours

People in this transcript

  • Aaron
  • Kent S
  • Mark Murphy
  • ryan7