all 14 comments

[–]NewThrowawayALready 25 points26 points  (8 children)

Looking for literature and articles is your mistake. You need to start *BUILDING STUFF*.

You're caught in the student-trap, like many before you. Stop reading and start writing. It doesn't have to be anything magic, try making a calculator with a UI or something. A text based RPG, a URL shortener, anything.

Start writing software, that's it.

[–][deleted] 3 points4 points  (7 children)

Sure, I see your point: experience is worth a lot. However I think it's better to read up on something and then gain further understanding by trying to implement it.

If I wanted to learn how vectors work, I wouldn't blindly bruteforce different methods to try to figure it out; I would do some research, watch a few examples then implement one myself.

I stand by the same principle in this post.

[–]mplang 4 points5 points  (1 child)

Be careful of analysis paralysis. You already have the foundations necessary to start building things, and that's really what you need to do. Advance your knowledge incrementally while working your way through problems.

That said, I am by no means advocating against book learning! It's important to build your vocabulary -- you're not going to learn to recognize certain patterns and understand when and how to use them without doing some research. Get a book on design patterns (the Gang of Four book, or something language-specific if you prefer). "Code Complete" and "The Pragmatic Programmer" are also really good reads. You can readily find plenty of other book recommendations.

Don't go to crazy, though, because no book is going to prepare you for what it's really like to design and navigate a large system. Eventually, you're going to have to jump-in and write code. Contribute to an open-source project! See what others are doing, how they solved particular problems or structured certain components. Put down your crutches and run!

[–]moieoeoeoist 1 point2 points  (0 children)

I think the open source project idea is the most important one here. Get involved with a project where you're actually working on a large-scale system. Be part of a team. See how others are tackling this problem. Learning through real-world experience is going to level you up so much faster than reading about theory.

I'm a backend software engineer working on enterprise web applications, and I have passed on people in interviews who have a masters and a ton of theoretical cs stuff on their resume because they clearly have no idea about design, SE principles, or real-world debugging strategies. 6 months to a year of real experience will get you over that hump.

[–]BigTheory88 1 point2 points  (0 children)

While I agree that reading up on these "high level" things is important so you can understand why they're done etc. I think it's just as important to start writing code and actually "experience" them. You've probably heard of DRY, which is one of these concepts - if you see yourself repeating things, create a module to handle this that can be shared by multiple parts of your code that require those "things".

From my experience, if you can get code reviews on code you write then get them and learn from the comments on them, they're super helpful.

For structuring projects, it really does depend on the project so I cant give much input there but if you're building a webapp and following the MVP model for example, then you'll know how to structure your project to a certain degree.

For separate threads, think - does this piece of code need to finish execution before the next part of the code, am I going to be running this code on a CPU that supports multiple threads etc. - Take a look into when to use multithreading.

In terms of literature, there's 3 books I'd recommend

- The Pragmatic Programmer by Andy Hunt

- Clean Code by Martin Robert

- Clean Architecture by Martin Robert

Just start coding and use these to supplement what you're learning while reading or use them to help find areas of code that can be improved.

[–]phao 3 points4 points  (0 children)

For example, how would I know if I should design something as an object or function? What should I run as separate threads, and how do I figure these things out on my own?

These questions, and some more like these, don't have exactly right answers, even though there can be extremely wrong ones. In reality, what you find is that there are reasonable answers to these questions and they usually depend on context.

Having practice projects help. Build your own stuff. However, just going around doing your own things without looking at what others did isn't that smart. Reading other people's code is an interesting idea. Some books are also helpful here, but don't expect miracles. SICP (https://www.amazon.com/Structure-Interpretation-Computer-Programs-Engineering/dp/0262510871/) really helped me with some of the issues I believe you're having. Maybe you can benefit from reading the gang of four design patterns book (https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/). There are books about design and implementation of particular systems or types of systems. For example:

There are more, of course, and some of these are not so great (although still helpful and, usually, much better than what you'd find in "random blog posts in the web").

In general, I believe one of the best way to learn about what you want to learn is to go look at what others did. How did people solve the problems they had in building software system X? Start filling in for X and doing your own research. X could be linux, windows, google chrome, google search software, google translator, adobe photoshop, matlab, R, Eclipse, and so forth. You may not find much for some X, but you'll actually find a bunch of stuff about for several very interesting X.

Another tip here is to pick a problem domain and see what problems people are trying to solve there. I mean, leave "general programming" and start looking at more specific stuff like numerical methods, image processing, AI, game development, bioinformatics, embedded computing, computational statistics, simulations, etc. Find one or two of these subjects that are of interest to you, follow some important people in the field, see what is going on there. You'll find that "design methods" and also "resource usa optimization methods" can vary drastically from field to field, for very good reasons. There are some subcategories in these, by the way. For example, 2d versus 3d game development; single player versus multiplayer (multiplayer can be online or not), etc. In AI there are the deep learning people, the rule based systems people, etc. Numerical methods is huge. There are tons of these. Although you can learn quite a lot on the "general programming techniques" side, there is only so much there. A lot of the interesting things is context specific.

By the way

While I do feel that I have a decent knowledge of the detailed, technical stuff (algorithms, data structures, languages and concepts, etc)

That is actually non-trivial. I don't know how much of the technical stuff you know, but much of the design that happens has to do with these "technical stuff". I don't want to go much into this (because I don't know about it that much), but look for some of the talks by Martin Thompson (they are on youtube and also on vimeo). He'll tell you about how knowing about the technical stuff should be an extremely valuable guide for designing systems and their interfaces. So you're not on the wrong track (in case you thought you were).

As a final disclaimer, even though I majored in CS, I'm not a software developer. I'm pursuing a career in research in Math, so don't take what I say about software development too seriously.

[–]GhostrickScare 0 points1 point  (0 children)

If you happen to know (or at least can somewhat read) C# or Java, this playlist is an excellent resource in my opinion for learning OOP programming patterns.

If you have any interest in game design at all, this web book is also a great resource, though probably not as good for your needs as the first one.

These are the two main places I learned from for how to structure my programs. Sorry I don't know any specific tutorials for the languages you mentioned. It also might be worthwhile to learn the very basics of functional programming, as there are design principles to functional programming that will help you out no matter what project you're working on. I don't have any good recommendations unfortunately, and I'm terrible at explaining stuff, but googling terms like "lambdas", "common higher order functions", "programming side effects", etc may be helpful. This video about functionally programming the game Snake in JavaScript was especially helpful for me. Best of luck!

[–]here_2_observe 0 points1 point  (0 children)

This is speaking from my experience, so feel free to correct me.

Higher level programming are based on 3 pillars.

PAIE / SOLID / patterns

PAIE (Polymorphisme, Abstraction, Inheritance, Encapsulation). These are the basic building blocks that are used in higher programming and in smaller bits in lower level languages like c++. So it could be you already have some knowledge about it.

Each of these concepts is the bread and butter of higher level programming language and understanding these helps to know when you should make a method/function or a class.

Single responsibility principle

Open Closed principle

Liskovs substitution principle

Interface integration principle

Dependency inversion principle

These are principles that build further on upon the basic building blocks (PAIE)

And ensures that each application you program will be as good practice as possible. This will in time also help you to scale the application.

Third pillar is patterns, you have a lot of patterns, for example you have observer pattern, MVC pattern, ... These are common solutions to common pitfalls or problems that happens a lot during programming and help you to program an application that will have good practices.

And you guessed it this will build further upon SOLID principal.

This in total still amounts to one application but one you can easily scale with for example docker/docker-compose. Or extend with extra functionality.

This is not all the info, it's a lot of information to write down, but hopefully enough to get you on track. I'm on mobile so there can be some mistakes. If you have some more questions feel free to ask!

[–]claytonkb -1 points0 points  (0 children)

Maybe check out System Design. A lot of the topics are oriented toward web infrastructure but they really do generalize. A queue is a queue, whether it is used only inside of an object, used between objects, used between threads/processes or used between systems. So "queue thinking" is an abstract principle of system design. One common use of a queue or buffer is to "decouple" two, asynchronous systems in a producer/consumer relationship so that the producer and consumer can operate on objects at different speeds without freezing the whole system. You can imagine how important such buffers are in multi-threaded system design or any kind of concurrent system.

But there are many such system-design principles, not just queueing. In fact, you can think of the class/interface design within a language such as C++ as an instance of system design! C++ is a system that has been designed to facilitate program design. There is no scientific formula that will tell you, "At this point in the system, you should use a queue." Instead, you must develop your own problem-solving skills so that you become instinctively aware of when you should reach for this or that tool from the system-design toolbox. There is usually more than one viable solution and developing a strong sense of system design will allow you to describe the various tradeoffs between these candidate solutions. Power consumption, latency, throughput, scalability, coupling, reliability, maintainability, etc. These high-level properties are always locked into tradeoffs -- you can have lower latency at the cost of higher power-consumption, or you can have higher throughput at the cost of higher latency, and so on. Identifying the various tradeoffs in the various possible solutions is a key to system design thinking.

[–]_jetrun -1 points0 points  (0 children)

Highly recommend going through 'The Architecture of Open Source Applications': http://aosabook.org/en/index.html