
Ask HN: How do you learn to build substantial, real world apps? - smckk
I am learning to build apps in android. Most of the tutorials and even books I come across have quite small examples to follow, usually 2 activity files and 2 layout files. Honestly, the progress to build a substantial app is a bit slow because the projects are so small. It feels like being stuck as a beginner.<p>Looking at examples of most apps, they are usually made up of 10+ class files serving the app. I want to know what resources are out there that help you make the move from learning to build an app by showing you the basics to something substantial with architecture and design patterns - not necessarily spelt out but present nonetheless.<p>I want to know how you made the jump to 10+ files in a project, what resources are out there that lead you to get to that level?
======
kadabra9
It sounds cliche, but "scratch your own itch".

My group of friends used to run a pool where we would handicap NFL football
games and pay out prizes to the top 10-15% of finishers each season. The pool
grew big enough to the point where it was a pain to manage manually, so I
ended up building a small app where we could create new pools, users could
sign in and make / edit picks, it would track the standings, etc. It would
scrape the final scores/results of NFL games to grade everyone's picks, and
each Tuesday it would scrape the consensus lines to set the spreads for each
weeks slate of games.

Im not really sure "how" I made the jump per se, it just became one of those
things I couldn't wait to work on. Anytime I ran into difficulty it was like
getting stuck in a video game, I would try new things until I fixed it.
Gradually over time things started to fit into place and a functional (but
clunky) web app emerged.

It wasn't pretty (this was a long time ago), but it worked, and we used it for
our pool for a few seasons without a hiccup. I still remember the afternoon I
made the "final" commit as one of the happier moments in my career.

~~~
vorpalhex
You don't achieve success by somehow avoiding failure, rather you repeatedly
fail (in small, safe ways), grow, and learn.

Perfect is the enemy of good. Your tech doesn't need to play buzzword bingo
out the door, it just needs to solve the problem.

------
semicolonandson
This is exactly what I'm covering with my Semicolon&Sons screencasts.

Basically I've run a profitable production web app for 10 years (~14k LOC,
200k monthlies, revenue higher than any day-job I could get) as well as a few
Android/IOS apps.

Now I'm creating videos where I show various real-world aspects of writing
software in the context of my own production code - e.g.

\- architecture

\- rapid response systems to production errors

\- dependency choices

\- data integrity guarantees

\- integration testing systems

\- softer stuff, like optimizing for SEO and on-page conversion.

There's not enough non-beginner material out there and I hope to help fill
that gap in resources.

They're all available here: [https://www.semicolonandsons.com/series/Inside-
The-Muse](https://www.semicolonandsons.com/series/Inside-The-Muse)

~~~
wolfgang000
I really like the videos, your content is very inspiring for a wannabe indie
hacker, keep going! by the way, a piece of unsolicited advice, add some king
alert for the subscription form, I added my email but after clicking it
nothing happens.

~~~
semicolonandson
Thanks for the advice -- will add that to the auld backlog.

------
insin
Clone an existing app.

You'll very quickly bump into real-world problems you've never solved before,
both in implementing the requirements of the app and in organising your code
as the implementation grows.

Plus the design is already done for you (which honestly feels like cheating,
as it removes an entire aspect of the app you normally have to worry about in
parallel with the rest of the implementation), so you'll also get experience
working to a design spec.

I've been scratching some of my own itches while learning Flutter, which has
resulted in a bunch of apps with a small number of screens, without user auth
or any complex API usage. A workout timer (2 screens), a simple trivia game (3
screens), a remote control (~5 screens), a sound/video/image board for SEN
kids (7 screens in a single ~3000 line .dart file)…

Then I tried cloning the app my gym was using to post workouts and log results
before it closed down due to COVID-19 - boom! [1] Just from this one app I've
gained experience with Firebase Auth, Cloud Firestore, Cloud Storage, co-
ordinating and navigating between 24 screens and counting, CRUD screens,
screens with multiple user permissions in play, sharing editable data between
multiple screens, some fairly complex dynamic display logic in the workout
editor, creating bar charts with user statistics, implementing specific little
interactions the original app has (like smoothly sliding a comment input into
view as you scroll down and sliding it out as you scroll up) and umpteen other
things I can't think of right now.

[1]
[https://www.youtube.com/watch?v=DvWJgZKj7cw](https://www.youtube.com/watch?v=DvWJgZKj7cw)

~~~
switz
This only works if you're extremely honest with yourself about the constraints
and you earnestly work through all of the edge cases and UX. If you don't have
the experience to know what those constraints are, you will likely miss many
things that go into what it takes to build a solid product.

It's so easy to ignore the real-world concerns of a product by just cloning
the visuals, sticking a ribbon on it, and calling it a day.

I find this to be a valuable exercise in moderation, but at some point you'll
need to build some products from scratch (and I'm not even really talking
about the code itself) to gain the requisite experience.

~~~
kerkeslager
I really don't have this problem at all when working on personal projects--my
problem is very much the opposite. Deep down, what I want to do at my job but
never have time to do, is create something _absolutely perfect_. So when I'm
working on a personal project, which has no time constraints, I work through
the edge cases and UX _far_ more than is necessary or reasonable. That level
of perfectionism is why all my personal projects always feel almost-done.

------
holografix
I think you’re looking for a process or heuristic in how to “make the jump” to
a large collection of files which typically represent a more _robust_ app.

What you’ll find is that it doesn’t typically exist.

Unless your app is following a particular category of app (is it a todo app,
mostly crud, is it just a skin over a bunch of read only APIs, is it a game?)
your app will grow organically and as the complexity grows you’ll naturally
start breaking things up, realising certain parts can be generalised where
it’ll be useful not to one, two or even three other bits of code but dozens
(don’t be afraid of a little repetition, MUCH better to repeat 5 lines of code
thrice than to create another function).

Also with more complexity and simple volume of code, testing becomes
indispensable. At some point it becomes difficult to foresee how
interdependencies in the code might be affected if you change something.

Running a suite of tests will save you lots of time. And you need test files
for that.

If you’re looking for __the way __to get you more organised I’d recommend
building a test for every function you write. It’s very interesting how that
changed my code suddenly every bit of code I wrote felt independent but
connected, it was also nice to feel like at any time I could feed a function
some dummy /simulated data and it’d spit out the same output. There was no
hidden state being mutated somewhere else. No global vars.

------
melenaos
Just create an app you want to use and keep adding features. You will end up
with a large app that is ridiculously complicated and needs refactoring. Do
the refactoring so it can become better maintainable.

Do that Asian for a number of projects and you will see that every project
looks different, maybe better maybe more complicated than it should.

~~~
welcome_dragon
I don't know what Asians have to do with it lol (I know it was an
autocorrect), but while this is a long term approach, it would definitely be
the way to go IMHO. The experience and reflection are key

~~~
karmakaze
28:00
[https://www.youtube.com/watch?v=04gsgRsH0yY](https://www.youtube.com/watch?v=04gsgRsH0yY)

------
stonemetal12
What you are asking about has nothing to do with Android development, so you
won't find that tutorial.

It is Software Engineering. SE, will be a bit generic and won't directly talk
about making an Android app. So you will have to take generic principles and
apply them to a specific domain.

------
AlchemistCamp
I just copied things I already knew about. I did a tutorial for a side-shotter
flash game. Then I made a breakout/arkanoid clone, which was much harder for
me. Then I made "Tetris with a shop to buy blocks". That one took me almost a
month.

The code was ugly, but each project got more sophisticated than the one before
and showed me the value of certain techniques (after having done things in a
more difficult way without them).

Tutorials are fine, but you really need to work on your own projects
afterwords and use what you've learned. You'll get stuck and have to struggle
through parts, and in the process learn quite a bit. Start with smaller
projects and work up to bigger ones.

------
tommyage
Mobile developer here, who published several apps on the stores.

Do not worry about the size of your app. Managing decoupled apps is way more
annoying then conciseley written ones. And by the phrasing of your question I
assume you are projecting the complexity of the codebase to the capabilities
of the app.

My piece of advice is the following: When developing for mobile modularize the
functionalities by screens and aim for a strong coupling within them. Even
when the functionalities are growing (proportional to the success of the app,
that is), you will not often see too many similiarities between them and the
redundancy is factored out easily.

Only when starting to develop a larger app which shares multiple screens
across it could make sense to bundle differently. In this case, you want to
structure the codebase by your tests. Most of the time, reusing a screen
creates plenty pitfalls, which can simply be avoided by not reusing.

Due to grouping the functionalities by screens, issues will mostlikely not be
related to eachother. Also, in my experience, libraries introduce more issues
then solving, so trying to keep the app barebone will often result in a
smaller download size and a more robust app.

When applying these thoughts properly a larger app could look like the
telegram client!
[https://telegram.org/apps#sourcecode](https://telegram.org/apps#sourcecode)

------
dec0dedab0de
Well I have not done any android development, and I know Java has some
specific quirks around classes, so maybe this isn't very helpful.

In my general development experience the amount of
files/classes/functions/modules/whatever you use is really just about
organizing your code in a way that makes it easier for you to work on one part
of the code at a time. The idea being that once you know you have part of your
code working the way you want it to, then you can forget about that part and
focus on the next bit.

As far as when and where to do those splits, it's not always obvious, but it
comes with experience in the language, and a greater understanding of what you
want your application to be. When in doubt, just get it to work as best you
can. Then when you find yourself digging through a giant method to debug 4
lines that could stand on their own, or copy/pasting a blob of code that could
be a function, or just wishing to yourself that there was a library that did
exactly what you needed, then take a step back and think about how to make it
better.

Sometimes the solution won't present itself until you have to go back and make
changes years later. In that case, fight the urge to throw it all away and
start over, but remember the pain for your next project.

------
peterkos
As others have said, try to clone something already out there! But start as
small as possible.

Like, for Instagram. First, just the scrolling list of images. Then, images
with text under them. Then, a tab bar with images and a profile. After enough
of this, a basic skeleton will form and you'll start hitting the fun edge
cases: how do you edit a user's comment? How do you make sure user data is
always in sync? How do you handle _every possible_ API error that you might
get, and _communicate_ that simply to the user?

Open source projects are also a great reference. As an iOS dev, I'm biased,
but I've heard Android code tends to err on the side of "meh, it works", even
in large projects, so be on the lookout for that. Software architecture tends
to be fairly consistent across platforms in my experience anyways.

------
wiseleo
The biggest change for me was adopting clean code practices.

What it meant in practice is writing functions as a collection of calls to
other smaller functions. Each function does only one thing. I spend most time
on naming objects, functions, and variables. It is hard in the beginning to
not use non-descriptive names, but then you have to re-read that code and
mentally rename it each time in your head while struggling to understand what
it does.

Writing test code to validate shorter functions becomes fluid. When you can
easily understand your code and can depend on it not breaking, you will find
it’s easier to add features and expand existing features.

You will find many good talks on YouTube, but they really summarize what they
wrote in books.

One good exercise is to reimplement built-in language algorithms like sorting
and string manipulation from scratch.

------
saluki
Since you have the basics, expand on that.

Build a more complex app that you would use.

So pick out a hobby or something that interests you that an app would improve
your experience with.

Plan out the requirements/scope and start building it.

Building any app you're going to run in to things that you won't find a
tutorial for, or you might have to combine a few tutorials to create it.

That's the best way to learn, is just taking on something and building it.

If you don't have any ideas, ask a friend or family member if they could use
an app. You'll learn even more if someone else is telling you what they
need/wish it could do.

Good luck expanding your skills.

------
easytiger
I don't mean to sound glib, but you just keep implementing the functionality
you need to accomplish the end result you want. However large the number of
classes is fairly meaningless.

Perhaps I'm missing something?

~~~
jfernandez
I guess one of @smckk's main points is that when one looks up tutorials and
guides they tend to be introductory. Meaning they don't go to intricacies of
critical refactors to introduce major new functionality etc.. i.e. I think
@smckk wants to see how people approach the thinking about changes beyond the
"initial build".

@smckk the closet thing I can think of that may help you is to visit large
company's engineering blogs that sometimes do small to large writeups on big
changes in their architecture, code organization style, etc. It's not as
detailed as seeing the actual changes line for line but it can help guide your
thinking of taking a piece of non-trivial code to another level of non-trivial
code if that makes any sense.

~~~
easytiger
That makes sense. But to me those are largely functions of experience with a
toolset/platform that are expanded with product iterations and not something
to dwell on.

------
projektfu
Every activity is basically a mini app. Take a gym log for example. It has an
activity for recording an exercise. It also has an activity for viewing the
list of exercises in a workout. It has an activity for viewing a list of
workouts. It has activities for editing each of those lists, discovering new
workouts, watching videos of exercises, taking notes on particular sets, and
adjusting settings. Maybe it includes social features, graphing, reporting,
etc. But whoever wrote it started with just a couple of activities and grew it
up.

------
brianolson
Part of 'software engineering' is the wisdom of how to organize a large
project. There are books on the subject, some of them good. One place I worked
had a book club that met one lunch a week to talk about them and what we liked
and discarded from each book. Ultimately I feel I've learned a lot by doing
over my 20 year career; so, go for it, make it messy on the first draft,
figure out how it would be better organized, make it better. I still do first-
drafts all the time.

------
janee
Tbh I would suggest joining a company that's working on something that sounds
interesting to you and has a strong sense of providing mentorship.

Like you mention there aren't tuts on complex systems as a single thing. I'd
say because complex systems solve quite specific things and usually delve deep
into domain specific problems that aren't of interest to people outside that
domain

------
villgax
If you try to look for any sort of standard approach to Multi-tenant apps or
even performing billing per API call there aren't good resources probably
because they are worth keeping to ourselves resources. The same goes to DB
migrations without losing requests & how to build your app with scaling in
mind.

------
nickthemagicman
I would start with frameworks. You'll learn how a well structured app looks
while also having the reward of building something cool.

There needs to be more books on concrete software development principle that
fill the gap between basic software dev 101 and software design patterns.

Like practical books on building an app.

------
lovelearning
Came across this project demonstrating modern Android development best
practices in a reddit discussion:

[https://github.com/igorwojda/android-
showcase](https://github.com/igorwojda/android-showcase)

------
soulchild37
Try search for open source Android apps in Github, and study their code and
architecture there.

Hell, my own Android app has just 1 Activity and it is making me money (just a
cup of coffee haha) everyday, does this counts as real world app?

~~~
me_smith
I'm curious, is that money from ads? or in app purchases? Thanks!

------
bluedino
Start reading about and understanding design patterns. Then look at some non-
trivial, open-source Android apps, see how they are put together. What
elements do they use? How do they pass messages and share data?

------
rtcoms
For Ruby on Rails, check this out
[https://www.railstutorial.org/](https://www.railstutorial.org/)

------
ykevinator
You can intern at a dev company, is that something you are interested in?

------
plantain
Incrementally.

~~~
egfx
To elaborate on this, you should start with an idea of what you want to build
and find the most bare bones implementation you can find. For example, for
[https://gif.com.ai](https://gif.com.ai) I knew I wanted to build a MEAN stack
app so I found a simple (a very very simple) MEAN stack project on GitHub with
a few Express routes for view rendering. This became the baseline of the
entire architecture. From there I followed pretty much the same paradigm I was
presented with to build the rest of the app. You end up with multiple files,
or large code structures after a lot of iteration. Removing is as important
midway through as implementing new code. The process is organic. You just
build it up, and work on it daily.

------
Ologn
> I am learning to build apps in android. Most of the tutorials and even books
> I come across have quite small examples to follow, usually 2 activity files

Two activity files? That's a lot. With Jetpack Navigation, you can have
substantial real world apps using one Activity.

I have programmed Android apps professionally for a number of years, from
substantial, as you describe it, apps for Fortune 100 companies, to smaller
apps for much smaller companies.

There are two things to consider looking for examples - one, is you want an
app using modern Android architecture. That it is using coroutines would be
one of the main markers of this. Also it would probably be using Navigation,
View Models, and Live Data. It would be written in Kotlin, of course. The
architecture being MVVM, or possibly Clean Architecture with use cases.
Possibly using Dagger for dependency injection.

You might find some older substantial, real world apps using architecture and
design patterns, but they might be ones not used much any more - maybe an app
written in Java that made direct non-Room access to SQLite to get and retrieve
local state (or, forbid, Shared Preferences), maybe Volley to access a web
API, Asynctasks to do background work, Loaders to load data - none of this is
current best practice, and much of it is deprecated.

If I had the choice of a model to be a small, modern example app, or a several
years old out-of-date substantial, real world app, I would choose the basis to
be the smaller, more modern app.

Google has some example apps. I think this is a decent one -
[https://github.com/android/architecture-
samples](https://github.com/android/architecture-samples)

Both the main branch, and the slightly more out of date dagger branch.

This has all the architecture you need for a bit. The main thing it is lacking
is network access, but you can learn that from other Google example apps.

What is architecture in an Android app? It can be thought of as a few things.
One is just a clear line from the ultimate authority of state (say a web API)
to the I/O of a screen. You tap a view, it goes to a fragment, under the
management of an activity and navigation - and the fragment sends data to a
ViewModel, which sends data to a repository, which sends that data to a remote
data source. There might be a response which filters the other way. So a clear
separation of UI and state model, and a clear line of transmission between
them.

Another way to look at Android architecture is in the clean sense. You have a
model for state which does not change much - organization-wide (like
enterprise-wide business) data models and rules which are the same across the
organization. These do not change much, and have no dependencies on classes
apt to change. Dependent on these organization-wide, system-wide shared data
models are data models that are specific to your particular app - application
specific data models and rules. Dependent on these application specific
rules/models are interface adapters like presenters (or view models, or
repositories). Then dependent on these interface adapters would be the UI, web
API and DB layer - the framework layer.

In both of these, architecture is the protection of the platonic ideal of the
critical data structures used from the flittering volatility of the input and
output of UI. In the case of clean architecture, it is protection from the
specific framework dependencies needed to store and retrieve data model state
as well.

In terms of design patterns, you make use of them in Android when needed -
from singletons ("objects" in Kotlin), to adapters (particularly for
RecyclerViews and such), to observers (used for Live data).

In terms of large and substantial apps, once you break out into different
teams working on different parts of the app, you will usually (although not
always) have the app broken into different modules for different features of
the app. As your main concern seems to be apps which have more than ten files
in a project, I take it you are not talking about apps so large they cross
this threshold into one with multiple modules used by different teams in an
organization within one app.

