Office Hours — Today, December 29

Thursday, December 24

Dec 29
8:20 AM
Mark M.
has entered the room
Mark M.
turned on guest access
8:25 AM
Kai H.
has entered the room
Mark M.
hello, Kai!
Kai H.
Hello Mark
Mark M.
how can I help you today?
Kai H.
By lending me your knowledge and experience
I have a small apps that has several chapter, each chapter with several topics. How would you model that?
8:30 AM
Kai H.
several chapters
Mark M.
I guess I'm confused -- do you mean that this app is an ebook reader?
Kai H.
I gave too little information :D
It's pretty much a representation of javapractices.com
So a chapter has a title and several topics, and a topic has a title and some content.
Mark M.
is "some content" represented by data (e.g., HTML) or is "some content" a bit of custom code that is in the app?
Kai H.
Some content is html/text
Mark M.
OK, that sounds like an ebook reader :-)
for example, *The Busy Coder's Guide to Android Development*, back when I maintained it, was distributed as an APK, as a custom ebook reader wrapped around the book content
8:35 AM
Mark M.
(in addition to being distributed in PDF/EPUB/Kindle formats)
specifically, my APK was an EPUB reader, so I used existing EPUB libraries to extract the chapters for display
Kai H.
So you would suggest the same for me?
Mark M.
well, in my case, that was an easy way to represent the content, since I was creating EPUB for direct distribution
you might just set up a directory tree in assets/ with your HTML, plus some JSON to serve as a "table of contents"
later, in addition to the EPUB, I packaged a database that contained a full-text indexed copy of the prose, for use in searching
Kai H.
OK
Mark M.
if you wanted the full-text index, you might consider just going with SQLite for the book content entirely
8:40 AM
Kai H.
So you didn't model it as data classes or something?
8:40 AM
Mark M.
well, this pre-dated Kotlin ;-)
Kai H.
I have that planned, to back it up with a database. Right now it's all scraped from the website in question.
So I don't control the content so far, which limits my options a little. Or rather I need to process it first.
Mark M.
if by "model it as data classes", you mean have individual classes per chapter or topic, definitely not
the only way I would do that is if I had custom UI that I needed on a per-chapter/topic basis, such as for demos
which is why I asked the question that I did back at the top
Kai H.
I meant something like "data class Chapter(val name: String, var topics: List<Topic>)!"
Mark M.
ah, yes, that I had
Kai H.
I guess I'll have a Fragment for Chapters and one for Topics.
Mark M.
that will depend a bit on your planned UI, but it's certainly not out of the question
Chapter and Topic would be be model objects, and ChapterFragment and TopicFragment would be renderers of those model objects
Kai H.
Exactly. At the same time, I wonder if using a data class for Chapter and Topic is worth it for an app of this size.
Which is partly why this question came up.
Mark M.
as opposed to... what?
Kai H.
Also I am not really satisfied with Chapter referencing Topic when the Topic might not be known yet.
8:45 AM
Kai H.
List<String> :D
Mark M.
"might not be known yet"?
Kai H.
And a Map<String, List<String>> I guess.
As I parse the content at the moment, I get all the chapters first, then when a chapter is clicked it get the respective topics.
Mark M.
ah, is your plan to scrape the Web site in real time?
Kai H.
It is for now. Later I wanna scrape it once, then use the content via a database and keep it current by scraping in the background.
Mark M.
does the site actually change? copyright is 2018, and the content seems... older
Kai H.
I actually don't know. There are these "new" pictures on some topics ;-)
So I just assumed and thought that if I implement the scraping logic, I can use it later anyway.
But I might end up not doing so.
Mark M.
agreed, though scraping is always a dicey proposition -- one design change in the Web page and your scraper needs a rewrite
Kai H.
Yes, it is.
And I have seen more structured web pages. I have already spent quite some time in trying to scrape it.
Mark M.
I assumed (incorrectly!) that you were going to scrape offline and package the updates with the app, rather than try realtime scraping
the advantage of only scraping offline is that when the scraper breaks, it doesn't affect your users
(by "offline" here, I mean scraping from your development machine or some server, not in the app itself)
8:50 AM
Kai H.
Yes. That is a step that will come in the future.
Mark M.
but if the content does not change frequently, scraping in-app seems unnecessary
Kai H.
Sure
It takes a lot of time anyway, so I might just do without.
Mark M.
then, the app itself is just a presentation of the material; you can use other tools in other languages for the scraping and packaging of that material
Kai H.
Yes, I could :D
Mark M.
BTW, that site's RSS feed suggests that it has not been updated since September 2018
admittedly, that RSS feed is rather truncated, so I don't know how much to trust it
oh, wait, there's a Last Updated date in the footer that also points to September 2018
(and if the In Memoriam is for the person who created the site... it might never be updated again)
8:55 AM
Kai H.
I assumed it was for another person
Mark M.
it certainly could be
FWIW, https://web.archive.org/web/changes/http://www.... also suggests that the site has not changed since September 2018
Kai H.
I guess if I scraped before hand and got everything from a database, then having data classes is pretty much a must or makes things easier, at least (if I use room for example).
You made your point ;-)
Mark M.
most likely, you will want model classes (as data class or otherwise) that match your data storage and how you will read it in
another advantage of parsing this off-app and just packaging the content is that it minimizes the number of write operations that you need to worry about -- it's down to things like history or bookmarks, none of which is absolutely essential
9:00 AM
Kai H.
I don't get the second part of your last sentence.
Oh, now I did :D
Mark M.
the primary content presumably is read-only
Kai H.
Yes.
Mark M.
any data beyond that which you wish to collect (visited-topic history, search history, bookmarks, etc.) is up to you
and you can choose how much of that to do and when to tackle it
plus, how you store that user-mutable data does not necessarily have to be the same as how you store the read-only data
Kai H.
I think my follow-up question is also answered. I was wondering if I have one or many ViewModels for the topics, as those change according to the chapter that is selected.
Mark M.
that will largely be dictated by your UI
Kai H.
But I guess there will be one ViewModel, with the topics changed if the chapter is changed (or rather when another topic Fragment is displayed).
Mark M.
from a class standpoint, my guess is that there will be at most one ViewModel class per fragment class
from an instance standpoint, it will depend a bit on how you use those fragments and whether multiple of them will be around at once (e.g., some sort of tabbed presentation)
9:05 AM
Kai H.
How would I implement multiple ViewModels for multiple sets of topics?
Without doing it hard coded.
Mark M.
what do you mean by "multiple sets of topics"?
Kai H.
Let's say there is a tabbed view of chapters. Each chapter would have its topics and a ViewModel.
So if there are 5 Chapters, there would be 5 VMs holding the Topics for each.
Mark M.
if by "5 VMs" you mean "5 VM instances" then yes
if by "5 VMs" you mean "5 VM classes" then no
Kai H.
I mean the first
Mark M.
right, so each ChapterFragment has a ChapterViewModel
perhaps pulling from a ContentRepository or BookRepository or something along those lines
Kai H.
Yes
(I already have ChapterViewModel, but right now that holds the list of chapters)
Mark M.
you may find that you do not need a TopicFragment -- particularly if you are doing tabs per chapter, there is only so much screen space, and so you might not have more than one topic visible at a time
9:10 AM
Mark M.
but, if you do elect to have a TopicFragment, it's possible that it has a TopicViewModel to match
Kai H.
So how would a ViewModel holding the topics for Chapter "A" be distinguished from one holding for Chapter "B"?
Mark M.
um, identifiers of some form
each chapter has an ID
Kai H.
:D
Mark M.
each topic has an ID
a TopicViewModel knows the ID of the topic that its fragment is responsible for displaying
depending on the data model, a TopicViewModel might also need to know the chapter ID
(particularly if topic IDs are not unique across your whole space, so the unique identifier of a topic is a chapter ID + a locally-unique topic ID)
Kai H.
Or the ChapterViewModels the topic IDs.
Mark M.
ummm... I think that sentence is missing a verb
Kai H.
Would you go with a chapter knowing its topics or a topic knowing its chapters?
Mark M.
is a topic contained by more than one chapter?
Kai H.
=> depending on the data model, a TopicViewModel might also need to know the chapter ID. Or the ChapterViewModels the topic IDs.
I don't think so.
Mark M.
then this feels like a 1:N relation between chapter and topic
Kai H.
I assume as much
Mark M.
from a relational database standpoint, a topic knows its containing chapter, as a foreign key
from an in-memory standpoint, it may not matter -- it all depends on what sort of API your repository exposes
in the end, given an identifier of some form, TopicViewModel needs to get to the content to display
9:15 AM
Mark M.
how you accomplish that is going to be dictated a lot by your data storage approach and the repository implementation that wraps around it
(plus caching considerations, etc.)
Kai H.
I plan to try and follow "Exploring Android" for all that :D
Mark M.
one key limitation of *Exploring Android* is that it has a fairly simplistic data model: a to-do item
there is no notion of, say, categories of to-do items
Kai H.
Which is why I have those questions :D
Or rather why I asked them here.
But I guess scraping first, then using the scraped data will be my way forward.
Should make some things quite a bit easier.
And for the rest there will be other office hours ;-)
Mark M.
yeah, once you figure out how you want to collect and store the content, other aspects of the app may become more obvious, in terms of how you want to approach them
9:20 AM
Kai H.
And I guess it's just trial and error and what works best for me on the way.
Mark M.
we always hope for short trials and few errors
somehow, it does not always work out that way
Kai H.
Lucky is the one who has someone else to help him try less long and err less.
My last question would have been "how to learn writing idiomatic Android Kotlin", but I guess it's also trial and error and searching stack overflow ;-)
9:25 AM
Mark M.
well, to an extent, we are still figuring that out
and the definition of "idiomatic" is also tied to the environment -- Jetpack Compose has its own concept of "idiomatic" that will look somewhat foreign to developers use to the classic View system
(er, "used to the classic View system")
9:30 AM
Mark M.
and that's a wrap for today's chat
the next one is *tomorrow* at 7:30pm US Eastern
have a pleasant day!
Kai H.
has left the room
Mark M.
turned off guest access

Thursday, December 24

 

Office Hours

People in this transcript

  • Kai H.
  • Mark Murphy