Ask HN: How to get good at designing big and complex applications?
Hi HN! I am a grad student with a focus on CS, specifically Software Engineering. I like to explore different technologies that are used to build a product and am fascinated by the way people design such big complex systems. For instance, I am taking a class on Operating Systems right now which also requires me to develop my own kernel. I am finding it very exciting, challenging and fun. I would really like to know what all I can do to get better at designing such big complex systems. I try to read open source but it always feels like a challenge. I don't know if I have the aptitude for this but studying CS and the thought processes of people who have spent so much effort in this field gives me a lot of joy. So, if you have any advice, resources, books or tutorials that you think might help me, please do share. I would be really obliged. Thanks!
46 comments
[ 3.7 ms ] story [ 111 ms ] threadThere's no single way. In fact, beeing a good software architect is all about having many ways in solving a problem, knowing wich solution is the most adapted depending on the context. All is about culture and cleverness To improve, you can :
- Follow/read the well know architects. For example, I read this blog https://martinfowler.com/ and watch most of the conferencies he gives.
- Learn the design patterns and the architectural ones.
- Read a lot of code, like github repos. It does not care if you're reading repos on a subject close to the one you're interested to. You need to see a lot of architectures to see some clever solutions some peoples have used to solve some specific problems. I don't think there's any shortcut.
- get interested in meta development. Like "why does the languages work the way they work ?", read about how code is produced in real conditions (what are the processes involved), etc.
For that part, I think it's true whatever is the field in which you want to improve
If you're really shy/impressed, maybe you can go with some friends and speak about it together. It will help you feel like you understood some things. Architecture is not filled only with youg peoples, and if you're a group of 20+ y/o speaking together, eventually the older ones will come and speak to you. then you can ask them what to read/watch to have deeper understanding
Besides Martin Fowler which was already recommended, I would also recommend the books by Robert C. Martin (Uncle Bob), and his "Clean" series - there are books "Clean Code", "Clean Architecture" - all of them are really good and useful and will give you a solid foundation to build on.
Other than that, the best thing you can do is to get practice & ideally surround yourself with more experienced developers. Either get an internship in a company building something more complex, or participate in e.g. Google Summer of Code.
Doing fun side projects is also a great way - you learn a lot and also have something to show & write about - win-win!
Do these techniques apply to games, or are they the wrong tool for the jobs?
[0] https://gameprogrammingpatterns.com/
The more you work in different applications, the more you discuss with your peers in your organization and other meetup groups, explore different design patterns (Martin Fowler), Follow well known Architects or Company engineering blog [0] posts, Try doing proof of concepts etc. Eventually as you progress with experience, I am sure you will get that knowledge.
I used to follow the below link [1] to understand how the systems work at different companies globally (e.g Facebook, Google, Netflix, PlentyofFish etc). This has very interesting content.
[0] https://github.com/kilimchoi/engineering-blogs
[1] http://highscalability.com/all-time-favorites/
As far as getting good at designing big and complex application, I'll give what I know.
1. Everything complex came from a small system. So make sure your small application works first. Twitter/Google/Facebook didn't get to what they have now on day 1. They failed a lot to get here.
2. Designing monolithic system is a lot easier than micro services.
3. Read a lot of codes and how different component interact with each other. For Python, projects such as Scrapy, Flask and Django are good example to start.
Think through the big problems and make sure you keep them in mind as your are coding the subsystems.
Make sure any code you write could be used by another system in case you need to break it apart later.
Make things pluggable though interfaces.
No global references.
You'll find that doing it right allows other features to be added that you haven't thought of yet. If you somehow force it to sort of work, you'll end up doing that for a lot of other features, too.
You design and write the cleanest, most simplistic & adequate solutions for problems as they arise and ruthlessly battle introducing complexity as features and scope grow.
Inevitably, after many years you will wind up with a system which by sheer size is complex. But only reason it works is because of the never-ending battle in the fight against complexity.
You can't design complex system without some buiding blocks which basically definition of 'complex', but you can design a complex system before it's deployed and it can succeed.
Itreatively designed system can hit a scalabilty wall or plateu where adding features is slower that a redesign. An evolving system design is a subject to a local minima of scalability and it needs careful apporach to maintain it.
This sounds kinda like a rephrased "there's no problem that can't be solved by adding another abstraction layer".
Even total redesigns will benefit from the experience and information, that you got from the simpler system(s). These are often hard to derive by other means.
Also understand the difference between these
there are very different roles, it's okay to be one and really good at one.BTW, you mentioned "design" so I'm going to hinge on that, design not the actual implementation. In that case study existing systems. 90% reading can teach you design, on actual implementation, more like 90% doing.
if you want to do the programming thing - learn low level programming, buy an arduino etc and learn to program it.
app development - build websites, mobile apps, desktop apps.
software engineering - contribute to a large scale app (kubernetes, postgres, etc)
computer scientist - study latest CS papers, replicate result, write your own paper and come up with your own ideas.
Let me explain...
A programmer can really program a computer. Think of the person that writes an operating system, a bootprom, all your embedded systems programmers. traffic light, very low level, operating near the hardware level/systems programming, assembly, C, rust, etc. your Linux kernel programs & device driver writers. You give them a device, give them the spec and they can bring it to life.
Application developers - build apps typically using higher level library and frameworks, think of your android, ios developer, microsoft windows app developer, CRUD website developer, they build apps for users. Most app developers call themselves programmers, but IMHO are not. Take away their framework, DB and most of them can't even build much with just a language and the stdlib.
Software engineer - more at the system levels, this is not about programming at the low level or user apps, but engineering software systems. Think of the folks behind AWS cloud, the sort of people that wrote zookeeper, kubernetes, Gnome, Unity, kafka, there's a lot of engineering discipline at this level. Code bases are usually in the millions and never really a single developer.
Computer scientist - new ideas, refinement of old ideas, algorithms & analysis. Their output is mostly papers and with some code to demonstrate the idea. This will be the person that gives you something like the raft algorithm or some new twist on machine learning.
Surely, one can intersect some or all of these, but it's also possible to be just one of these. 80% of the companies out there are hiring app developers and that's what they care about.
Experience > theory for such a topic. Go ahead if you find it interesting, but don't expect to become an expert on the topic just by reading about it ;)
Each has a completely different trajectory at this point in your life.
A great example is to read the great debate between Andrew Tanenbaum and Linus Torvalds over kernel design as its closely related to what you're currently studying.
Linus would have clearly failed Tanenbaum's OS class.
Yet I use Linux every day, as does millions of others, while Tanenbaum's MINIX is on a CDROM that came with the book that I bought for my OS class.
This is not to say Linux is still a monolith, but that would be getting in way too much details.
You sure about that? Do you use an Intel CPU?
https://www.zdnet.com/article/minix-intels-hidden-in-chip-op...
Now, let me ask you this.
If someone was to ask you either of:
1. "Between MINIX and Linux, which is a great example to study as an OS that's deployed on billions of machines worldwide and used by millions of engineers?"
2. "Between MINIX and Linux, learning administering which, offers me the best job prospects in the general tech industry?"
What would be your answer in each case?
Write small and simple programs.