Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Which are the best resources to learn software architecture?
135 points by labarilem on Jan 31, 2020 | hide | past | favorite | 34 comments
I'm a software engineer with ~4 years of experience in the IT industry. Since I've always liked designing systems (of any kind), I'm thinking I'd love moving to a software architect role. Currently I'm working closely with some software architects and I guess this can count as practice. But what about theory? Which are the resources (courses, books, etc.) that helped you become a great software architect?



It depends on what you mean by Software Architecture. I normally see 3 interpretations of it.

For some people, S/W arch is writing readable, maintainable code. Things like Design patterns, FP, TDD, microservices etc. There is a lot of literature on this out there.

For others, it means having the ability to design the next Kafka/Spark/React. You can get basic theory for this by reading books on Domain Modelling, Distributed computing and Algorithms. So books like The Algorithm design manual, Designing Data intensive Applications, The Parallel and Concurrent Programming in Haskell, Functional and reactive domain modelling etc. The http://aosabook.org has good case studies to read as well. However, to actually build these systems require facing the problem in the 1st place and being unable to use existing systems to solve it. Or doing phd in them. It happens rarely.

Finally, the last one is my day job. Which is to convert ramblings and fantasies of leadership into a production systems, minimizing the number of curse words people use when working on it. I haven't really found any good guides to do this though. Things which help me are:

- Always thinking what could go wrong. And if it does, who should be notified if the system can't recover. A lot of times when I don't have the answer, I ask around. Things like slack channels, mailing lists, or even having coffee with people in industry who have tackled stuff like this.

- Communication skills. This doesn't mean small talk, but being able to have conversations and meetings which help define requirements and ensure everyone is on the same page. Also making sure there are hard numbers. ie. instead of "fast","responsive" etc, get latency, throughput, uptime numbers.

- Understanding business/technical capabilities and limitations. Things like business impact(LTR etc), capabilities of current infrastructure, skill levels of various people/contractors involved etc


https://github.com/donnemartin/system-design-primer

This is geared for interview prep but I found it a very concise overview of how to build many kinds of apps.


> minimizing the number of curse words people use when working on it

A very noble goal :)


I was in the same situation as you a couple years ago. I'd taken programming classes in high school but I was unsure how "real" software was written.

So, I started learning about design patterns. In particular, I spent a lot of time reading through this site [1] and "Head First Design Patterns".

It was a mistake.

I've used maybe 2-3 of these design patterns when actually writing code, and never because I intended to use, say, a factory or a singleton -- I wrote what code I thought was most appropriate and it turned out to match an existing pattern.

--

Here's what's more valuable to learn:

- SOLID principles

- Realizing that what depends on what in your web application matters.

You want your business logic depending on your DB access code and your web layer depending on your business logic.

You do NOT want your business logic depending on your web layer.

- Realizing that your web app is really just some business logic which has a HTTP interface.

- Organizing software into layers. In a web app you'd have layers for middleware, controllers, business logic, and database access.

- Folder structure. I have a folder for each layer and try to have a descriptive name for each file in it. If a folder is getting messy, add another folder inside it with a descriptive name.

- Understand that refactoring is a fact of life. When you start a project, there's no way you can think of the optimal design up-front. This means you'll write code, accrue technical debt, and will need to refactor. Realize that this is 100% normal.

[1] https://sourcemaking.com/design_patterns


You don't want your business logic to depend on anything other than interfaces that it "owns". The actual database access code would be an implementation of such an interface. In other words, the business logic specifies in abstract terms what it needs, and the code surrounding it provides that.


Thank you for this comment; I will keep this in mind.

When working with a language like Go, where I have a DB access layer where I'm running raw SQL queries, I agree with this.

When working with Rails, though, I typically just make ActiveRecord calls in my service layer; it's simpler.


How do you write unit tests your service layer then? Unit testing is much more important in dynamic languages, because there's no compiler to protect you from basic mistakes.


I am currently a big fan of the hexagonal architecture which is pretty close to what you describe as far as layering.

https://blog.octo.com/en/hexagonal-architecture-three-princi...

https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-a...

I also advocate for packaging by feature rather than layer (each feature defines its layers)

https://hackernoon.com/package-by-features-not-layers-2d076d...


If you want more literature on that topic, it's usually referred to as Domain Driven Design where I'm from.


Small quibble, I really like inverting the (business logic) –> (persistence) dependency. That way your business logic drives everything, which aligns with your point about the app being "logic with an HTTP interface." Agree wholeheartedly with the rest.


Thanks! Are you suggesting business logic depends on persistence or persistence depends on business logic? How is the second option possible?


The second option is possible if you declare an abstract dependency (preferably just a contract like an interface) and make your persistence layer implement it. I highly recommend "Clean Architecture" if you'd like to learn more about that approach.


Still, it may prove useful to know the design patterns terminology. In my experience, it helps when discussing with other software engineers and sometimes interviewers ask you question about those patterns.


I found Designing Data-Intensive Applications[0] by Martin Kleppman to be the most eye-opening system design book that I've read. He really describes well how awful things get once you have to coordinate more than one physical machine - the number of things that can go wrong is staggering. I would say this book is as scary as Java Concurrency in Practice was - and that book was scary enough to get our company to change languages.

I think one of the best ways to learn software architecture is to have a clear view of what the challenges are, and the Kleppman book does a really good job of providing that clear view.

[0]https://dataintensive.net/


What language did you change to? Please say Erlang and/or Elixir!


We went to Clojure, and we've been very successful with it. But the BEAM is a great choice too! Immutable data structures make concurrency manageable, if not easy.



Despite the url this is not specific to azure. https://docs.microsoft.com/en-us/azure/architecture/patterns


For me, one of the pieces that really helped me understand architecture, was doing ops for years. Deploying systems, designing deployment solutions, and understanding how services fit into their environment helped me understand the solution as a whole. I was more able to come up with simpler, quicker to implement, solutions.

However, at the same time I was also doing lots of software development. I tried out lots of different solution styles. So don't ignore that aspect.


Sandi Metz’ POODR is the best I’ve seen on OO software architecture.

https://www.poodr.com/2nd-edition-faq


Her 99 Bottles is also great.


If you really learn and understand the SOLID principles then you already have better tools in your architectural toolbox than most “software architects”.


Perhaps a good way to learn architecture is directly jump into it. Try spinning up a complex personal open source project. The first architectural problems you will encounter will occur once the first set of new non-original requirements creep in. You will notice: complexity and competing concerns. You will need to make hard decisions to reduce complexity to allow better scale into the future and balance to resolve competing concerns. Practice is a great teacher.


I've been following Mark Richards at https://www.developertoarchitect.com/ for a while. I convinced my work to send me to his three day fundamentals seminar, and it was worth it. It was a top-down view of the architect role, and deep dives into different design decisions. Lots of hands-on exercises in small groups.

Super friendly guy, too. (And a board game geek.)


Internal resources (papers, wikis, talks) at big companies (AWS, Google) have been massively instrumental for my learnings.

Thankfully, some of these things have been opened up:

- https://aws.amazon.com/builders-library

- https://www.youtube.com/user/GoogleTechTalks



"Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives" by Nick Rozanski, Eóin Woods. Found this book really useful due to its methodical approach on views and perspectives. It really helped me to structure and clarify my thinking around complex software systems and communicate with stakeholders in a better way.


All the advice above is good, but if I were you, I'd take a look at functional languages and the architecture they yield as well.


Sounds like a good idea. Which functional language(s) would you personally recommend for this use case?


Well, it really depends on what your current stack is. If you're doing .Net then F#, if you're doing Java look at Closure and Scala. You can look into or Erlang Haskel as well.

I'm saying this because functional programming has the potential to simplify software architecture in some cases and make you a better developer or architect. Learning a new paradigm makes you question current practices more and that is a good thing imho. Recently I've been looking into Racket and I'd probably never do production stuff on it but it's been a real eye opener to me. I also like F#. There are a lot of resources out there, one of them is Scott Wlaschin, look him up on youtube.



No one's mentioned this book [1], which is a great catalogue of concepts, useful in architecting codebases.

[1] "Design Patterns: Elements of Reusable Object-Oriented Software"


[The Pure Function Pipeline Data Flow v3.0 with Warehouse/Workshop Model](https://github.com/linpengcheng/PurefunctionPipelineDataflow)

It systematically simulates integrated circuit systems and large industrial production lines.

In the computer field, for the first time, it was realized that the unification of hardware engineering and software engineering on the logical model. It has been extended from `Lisp language-level code and data unification` to `system engineering-level software and hardware unification`.

It brings large industrial production theory and methods to software engineering. It incorporates IT industry into modern large industrial production systems, This is an epoch-making innovative theory and method.

There are only five basic components:

1. Pipeline (pure function)

2. Branch

3. Reflow (feedback, whirlpool, recursion)

4. Shunt (concurrent, parallel)

5. Confluence.


I think that Entity-Component-System is THE architectural pattern for building complex applications

https://en.wikipedia.org/wiki/Entity_component_system

http://adventures.michaelfbryan.com/posts/ecs-outside-of-gam...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: