Settings

Theme

Ask HN: How do you learn to build substantial, real world apps?

87 points by smckk 6 years ago · 47 comments · 1 min read

Reader

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.

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.

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 6 years ago

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 6 years ago

    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.

  • ddek 6 years ago

    > It sounds cliche, but “scratch your own itch”

    Couldn’t agree more. What better way to learn development than actually experiencing the direct results of your actions. Not only do you practice app development, your UX design skills will Improve dramatically.

    About 10 years ago, while at school, I achieved the second highest non-degree qualification in piano, an LRSM diploma. But, gone are the days of being able to or even wanting to spend 4 hours a day practicing. I needed to get more efficient. The problem is that I’m objectively terrible at practice - I learn the first page, then enjoy playing it so much I never get on to the second.

    I made an app that helps me with this. I upload an svg score (lilypond, I use Mutopia scores then correct any discrepancies with whatever urtext I have), then use the app to break it into a tree of segments. The app then shows me, for 5 minutes at a time, the first 5 segments I haven’t marked as completed. Right now, it does nothing more, but it’s fantastic.

    It’s also objectively terrible proof of concept code, but crucially I’ve learned more about the UX requirements with the POC than I would ever have learned by planning ahead.

semicolonandson 6 years ago

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

  • hazz99 6 years ago

    I recently posted an AskHN about this exact thing.

    Just want to say there is a huge vacuum for this sort of content, and I'd definitely pay for it!

  • stevewodil 6 years ago

    When I enter my email and click the Get Episodes button, there's no indication that anything happened but a POST request is made. There should be some confirmation that the submission worked.

    I'm particularly excited for the "rapid response systems to production errors" and "integration testing systems" parts!

  • wolfgang000 6 years ago

    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.

  • cagmz 6 years ago

    I really like your series, especially your workflow tips and anecdotes. I could do without being interrupted mid-video to ask for my email, though.

  • dempseye 6 years ago

    Thanks for these screencasts. Very informative. You sound like you grew up in Rathgar or Rathmines.

insin 6 years ago

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

  • switz 6 years ago

    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 6 years ago

      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.

    • nwsm 6 years ago

      Unless you try.. using it?

holografix 6 years ago

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 6 years ago

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.

stonemetal12 6 years ago

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 6 years ago

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 6 years ago

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

dec0dedab0de 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

    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 6 years ago

      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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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

https://github.com/igorwojda/android-showcase

soulchild37 6 years ago

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?

bluedino 6 years ago

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 6 years ago

For Ruby on Rails, check this out https://www.railstutorial.org/

ykevinator 6 years ago

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

plantain 6 years ago

Incrementally.

  • egfx 6 years ago

    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 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 6 years ago

> 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

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.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection