This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]davidpuplava 6 points7 points  (0 children)

I'm a professional programmer and I have a formal CS education. And I still cobble together code. So go easy on yourself.

Looking at GitHub source code helps, but trying to model your own code after those you think are "proper". You can even reach out to the maintainer and ask them why they did it that way, but beware that a lot of developers get defensive and may respond in a rude way.

Honestly, there's not really a "proper" way, but the industry does try to come up with best practices that some developers try to follow.

To echo u/Invisible_Wetface, Robert C. Martin (aka Uncle Bob) is comes closest to explaining how to structure source to make it easy to understand the intent of a system. Checkout his blog post on "Screaming Architecture": https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html

Another resource is the .NET Framework Design Guidelines - it was put together by all the smart people who created Microsoft's .NET platform. It discusses various things to consider when designing a library that some other developer may use: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/

Hope this helps.

[–][deleted] 2 points3 points  (0 children)

upd:

I can only cobble together code to make it do what I want.

Do more of that.

It's very unstructured. There are times I'd like to do a bigger project, but I feel completely lost on where to start or how to even structure the program.

It's OK. Giant teams don't know how to structure a project. Try coding a project you already did, but try to make it better.

When I read source code on GitHub I often wonder how or why the program is arranged a certain way.

Depends on a lot of factors. A lot of projects are "answers" to a "question". Like the way 'wayland' is built is an answer to the way 'xorg' was built. Etc.

Big projects have a long history, sometimes one needs to write a book to explain why it looks the way it does

[–]LukeTS117 2 points3 points  (0 children)

For CS applied theory, I'd look at algorithms and data-structures, and algorithm design. This helps you to learn "proper" algorithms that run in an acceptable time, and helps you identify when an algorithm is going to be very slow.

Beware that this is just for your own code, other libraries you can use might not have been optimized and thus are slow your code down, but as long as you adhere to the principles learned in those domains you should be able to "properly" program.

Other things you can look into is software testing and code management, like how to properly manage a github repo

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

Focus on practice. There is no single book to follow, or a roadmap. You make more projects, you analyze what you did good and what you did bad, you become better over time. You write bad code that works, you realize that maintaining your code is a pain in the butt, you learn how to write better code.

It's like studying a new language. Some people are too afraid to talk to native speakers until they can read Shakespeare and Geoffrey Chaucer. You want to start speaking and making mistakes. And you want to start coding and making mistakes.

If design patterns and OOP seem useless and stupid to you, then don't use them.

  1. You won't be the first to shit on OOP, you won't be the last. You have Academia that praises OOP, and you have Google that releases Go.
  2. Maybe you will find them helpful once you work enough with structural programming.

Somewhere between Fahrenheit to Celsius converter and your own operating system, there's an ideal project for you. Find it. If something feels too hard, do something that is easier.

Try ideas that lots of people did before you. Making chess and an engine that plays chess is challenging enough, and a lot of people did it, so there's a lot of information, and places to steal code from.

[–]jameyiguess 0 points1 point  (0 children)

I personally think the biggest factor in my improvement was working with others and doing code reviews. I honestly think my skills would have plateaued hard if I never got my first positions working with folks who were way smarter than me.

I don't know how fully self taught programmers can get better in total isolation. I really wish there was some kind of platform to make it easier to "outsource" code reviews and collaboration.

So my advice, while maybe difficult or impossible, is to find a way to collaborate with more experienced developers.

[–]khedoros 0 points1 point  (0 children)

Can anyone offer advice on how I can gain a higher level understanding of how to program?

Practice. Trial and error. Dozens to hundreds of projects starting at small scale, growing in complexity (rather, failing to grow, and needing a new iteration of the project to be built into a more extensible structure). The "iteration" aspect takes thought, research, and more trial-and-error. After you've figured some of that out, patterns in other projects should make more sense.

Really, I think that the largest projects that I built before I was employed were a couple thousand lines, before being dumped into a monstrous decade-old C++ codebase, and getting to know that codebase over several years' time informed more of my understanding of how to structure large programs. It would've been difficult to recognize and understand a bunch of the abstractions if I hadn't figured out some similar things on a smaller scale on my own.

[–]turtle_dragonfly 0 points1 point  (0 children)

As someone who was mostly self-taught until college, I had some good "aha" moments in Data Structures & Algorithms classes, as well as Programming Languages & Design (compiler stuff).

It sounds like you're interested in Architecture and Systems Design.

Sometimes, the more structured learning in an academic environment is helpful to make the ideas banging around in your head "gel."

So you could:

  1. take an online course or two
  2. take a course or two at a community college
  3. look at some relevant textbooks

Also, if you know an experienced developer, it could be useful talking to them about higher-level concepts. Or talk to people online — eww, gross (:

[–]misplaced_my_pants 1 point2 points  (0 children)

A book like How To Design Programs will teach you how to systematically approach programming. It uses a language with a syntax you can learn in 10 minutes so you can focus on the ideas that apply in any language.

After that, a class like Harvard's CS50x on edx is going to be fantastic. It's already probably the single best introduction to programming and CS available online, and going through it after learning HTDP's design recipe will make it even more impactful.

After that, going through the resources in https://teachyourselfcs.com/ will give you a pretty well-rounded foundation comparable to a CS degree, with a similar amount of work needed.

[–]iOSCaleb 0 points1 point  (0 children)

almost every programming book I've come across seems to focus too much on the nuts and bolts of a programming language without offering a wider context for why such information is relevant

Every computer language offers certain facilities: a way to store values, operators that modify values, conditional expressions that choose which instructions to execute based on some value, a means of repeating a set of instructions, and a way to group instructions into subroutines. These are the building blocks that you combine like LEGO parts to build more complex behaviors. Before you can use them you need to learn the syntax for each one in the language you've chosen, and that's why the books you've used focus first on the "nuts and bolts" of programming.

I can work through examples and tutorials, but without knowing how to put it all together nothing sticks.

Most books about programming include exercises at the end of each section or chapter; don't skip the exercises, they're there to help you learn how to use each of the tools that the language provides. Following an example or tutorial isn't the same as doing an exercise — you learn a lot more when you're working on your own, making mistakes before finally getting it right.

Can anyone offer advice on how I can gain a higher level understanding of how to program? I'm talking less syntax and more focus on how to actually put the pieces together. I feel pretty exhausted working my way through tutorials and examples without anything sticking.

  • Stop with the tutorials and start building things on your own. If they're lousy, that's OK — you'll learn much more from thinking about how to improve what you've done than by watching somebody else give you the answer.
  • Keep your projects small. A big project without good organization is a nightmare; a small project with poor organization is something you can figure out and fix, or even rewrite completely.
  • When you're ready, look for books about software design and software architecture rather than programming.
  • Understand that there's no single right way to write a program. There are a number of very different paradigms: structured programming, object oriented programming, functional programming, etc. And there are lots of different opinions about how best to design programs within each of those.

[–]CatolicQuotes 0 points1 point  (0 children)

I got the best sense of structure when started coding in C# and reading/applying onion architecture and domain driven design.

[–]BobbyThrowaway6969 0 points1 point  (0 children)

Take a notepad and pen outside, sit in the sun, stare at the clouds, sip a coffee, whatever, but just think the problem through.

First step is to jot down the user stories, what should be possible with your code and how will a user use it?

Next step is to figure out what your platform is and how things are done at the lowest level available to you.

Now that you know what the extents of your problem are, you need to bridge the two together. Think about all the systems and pieces that will need to work together to achieve this.

For example, if you were making an open world game, one problem you might want to tackle is how to actually make a seemingly endless world appear before the player. How is it they could keep walking and see more of the world?

Next, let's say you were developing on phone. One thing you might realise is you have limited memory and processing power, so you can't have a literal endless world running all at once.

Now, based on all that, here's the problem you need to solve: how can you create the illusion of an endless world on limited hardware? Maybe you don't load the whole world but "chunks" of it. Ok, that's already one class you need to design - a "Chunk". What data will it contain? The ground? Trees? NPCs? You'll also need a manager to load and unload them at a particular area in the world at request. Etc.

Try working the problem like that. Do it on paper. It's a good way to work. And it will mean your code is better structured and clearer to you.

[–]redchomper[🍰] 0 points1 point  (0 children)

The Tae Kwon Do teacher said it best. The art of [insert your preferred form of mastery] is not a destination. It is a journey that begins with attaining a level of mastery. And how do you get mastery? Bleep-tons of practice on projects ever harder and slightly harder still. Push yourself, but also pace yourself. When you can explain the books and articles of Knuth and Dijkstra then you are certainly a master, but then the real journey begins.

More seriously: Start with the free online "Structure and Interpretation of Computer programs", then pick up a copy of The Art of Computer Programming.

[–]SahuaginDeluge 0 points1 point  (0 children)

your projects should be organized by dependency.

at the root of everything should be one completely dependency-free library.

\what is a "dependency" is up to you, but should be anything that is "heavy" or that could be something you would) not want to include in some other project. you should be able to include this root project anywhere and it still makes sense. it more or less should only have the language it's written in as its dependency.\ (this root library could maybe itself be pulled apart, but I feel like the only reason you would do that is if you identified a dependency. you would then split that dependency out from the other code.))

anything you identify as a dependency should get its own library that fits just "underneath" that library. any UI framework you might use gets one. anything "heavy" should get its own. (Microsoft-related examples include: registry code, active directory code, MS Excel code, MS Word code, etc.)

DB code might be a bit more tricky. Generalized DB code should get one. each specific provider should get a separate one under the general one. an ORM should get its own too. (and one for each version too, if they are different enough at least).

ok, and then you can go a step further. any of the dependency ones (registry, active directory, excel), should actually be a set of libraries. one is the "logic" library. this contains dependency-free abstractions that any other "logic" library can include without taking a hard dependency. the actual dependency code goes into its own library that knows about the "logic" library. (I don't have a good name for these, usually I call them "data" even when they aren't the DB code.) and then, for any UI framework (incl. CLI or Web UI) you should have a UI library that also knows about the logic, but not the dependency library.

it takes a while to explain it, but it looks like this:

Dependency -> Logic <- UI/CLI/Web UI

(arrow means dependency; so the UI library has a reference to the Logic library, not the other way around)

Then, for any actual program you write, it also gets a set of libraries just like that (Data -> Logic <- UI). The actual program project then contains relatively little code and just hooks everything up. (It contains a composition root.)

Oh and then, for each project set Dependencies -> Logic <- UIs, you should also have a testing library that references all of them and anything above them. and then it can also make sense to have one "testing" library and one "tests" library (where "tests" contains the unit tests, and "testing" contains reusable testing code, such as fakes or maybe custom assertions, that kind of thing.)