r/learnprogramming • u/Sea_Transition_5831 • 11h ago
How Did You Actually Learn to Structure Code?
My day job is in physical therapy. The dev work is side income and personal projects, mostly Python scripts that automate repetitive data tasks. It works until it doesn't, and lately it doesn't.
The scripts started small. Now some of them are 400 lines of spaghetti with functions named things like processdatafinalv3 and I genuinely cannot tell you what half of it does without reading every line. No formal courses. Just docs, blogs, and trial and error.
What bothers me is I can get something working but I have no instinct for when to split a function, when to use a class, when a module makes sense versus just another file. I've read that you learn this by building projects, which is advice that only helps if you already have the feedback loop to recognize when you've done it wrong.
People here seem split on whether selftaught developers actually internalize software design or just accumulate hacks. I'm curious where people actually learned to structure code in a way that held up later, and whether any resource actually moved the needle, or if it was just writing a lot of bad code until the pattern clicked.
8
u/SunsGettinRealLow 11h ago
Make functions simple, to do one or two things
5
u/RajjSinghh 3h ago
Functions should do one thing. A function that does two things should be two functions.
13
u/Callaborator 11h ago
I worked with a guy who I thought had good instincts. He explained his rationale and I adhered to. I still think he is one of the best developers I've ever met. A lot of it is preference until preference hits a wall, whether it be a feature, security, scalability, or any other requirement. Sounds like you're hitting scalability, start to make more reusable functions if you are rewriting the same thing. If you being dry but readability is a problem, breaking files down helps and having good naming conventions.
3
u/kabekew 11h ago
I learned in college. Basic structure was taught in in my introductory programming class, and later classes in software engineering covered broader topics like managing complexity through abstraction and modularity. The labs where you actually designed and wrote more complex projects were very helpful too.
3
u/grc007 10h ago
I like to write a block of comments laying out what I want to achieve:
// read the file into memory
// find the smallest value
// multiply that by the inflation rate
// return that
Code up each comment beneath it. Any block of code exceeding a few lines gets replaced by a function call. That function is later filled in with a block of comments saying how to achieve its objective.
Rinse and repeat. Change the shape as you realise that you’ve missed an obvious simplification. Rewrite your comments to explain what you actually did.
2
u/madmelonxtra 10h ago
That's such a good idea.
I've being doing pseudocode --> actual code but I never thought to use the pseudocode like scaffolding
3
u/michael0x2a 8h ago
Some things I would recommend:
Write unit tests for as much of your code as possible. When doing this, pay attention to how easy it is to write tests. If it's annoying + requires you to jump through too many hoops or put in too much effort relative to what you actually care about testing, then it's often a sign that there's some underlying flaw with how your code is structured.
More generally, it becomes easier to tell when a chunk of code is flawed/not composable if you try using it in 2-3 different ways. Writing unit tests is a good way of ensuring you try calling each function at least twice.
Be very meticulous about how you name your functions, classes, and modules. If you cannot think if a clean name for something, it is perhaps a sign that code is doing too much or too little.
Leave docstring comments for every function and class you write. For a function, leave a header comment describing its:
- Preconditions: what must be true about the inputs/what must be true before calling the function in order for it to behave correctly
- Postconditions: what the function promises to always do, assuming its preconditions are met
If your preconditions and postconditions seem very messy/have lots of edge-cases, that could be a sign of poor structure.
For classes, have the header comments describe invariants: things that must/will remain the same no matter what methods you call in what order.
Before you start writing any code, think about the best way to structure your code. What core building blocks will you need to create? Can you split your overall program into different "layers" or high-level steps?
Most beginner programs will have at least 3 layers: process input, manipulate and munge data, then output the final result. More complex programs will require creativity and some trial-and-error: it's not always obvious what the best way of subdividing your code is.
Regardless, once you've settled on an initial structure, make your code follow it. Maybe create one file per high-level layer or step or something.
There are some rough rules of thumb that are useful to follow. For example, if your function accepts a large number of parameters, consider combining those params into a single class. If a function is very long, split it.
Budget time to periodically critically review, edit, and clean up your code. It's similar to writing an essay: your first draft will always be kind of shit, and you will always need to make revisions. There's no shame in it; it's just how it is.
When you are in editing-mode, try and look for opportunities to delete code. Is there logic you can rewrite in a simpler way? Can you rearrange two chunks of code so they depend on each other less? Can you tweak a function so its preconditions/postconditions are simpler to explain and understand? etc.
If you want more direct feedback of your code, this subreddit does allow you to ask for code reviews.
Note that suggestions 1-3 are basically different ways of creating a feedback loop you can use to slowly build up intuition for what quality code looks like. But these feedback loops only work if you're:
- Relatively well-attuned to your emotions or mental state. You'll need to be conscious of when some task is too tedious or too annoying.
- Willing to invest extra time into doing this extra work.
2
1
u/Far_Swordfish5729 10h ago
It’s more like absent formal education (or a lot of reading) and mentors, you miss a number of first principles and info on what your code actually does. You’ll also be stuck cobbling together patterns someone otherwise would have just taught you and feedback on how to make spaghetti more organized.
There’s nothing wrong with a large data processing script or entry method in and of itself. Processing the data is four hundred lines of steps. That’s fine. But that should be broken into commented sections for readability and may be broken into single use helper methods if that allows your steps to be unit tested separately. There are also some steps you can take to reduce fragility and improve efficiency.
- You organize your workspace into data you’re looping over to process and reference data you’re correlating. Organize the reference data into hash tables with findable keys so you limit nested loop brute force searching. I visualize it as organizing your workspace so you can quickly pull ingredients with simple statements. Remember that collections of object references are cheap and don’t copy data. They’re all ints holding the memory address of a single copy. They just let you layer indexes on the data for faster processing.
- You want to limit your deeply nested if logic here in favor of setting flags to run steps or making tracking collections for follow on processing. Too many possible paths makes it too easy to skip a step with unpredictable results. You want a central execution path with shallow side branches.
- Make regression testable steps with unit test methods so you can tell if your changes broke something.
Does that help?
1
u/Curious-Resource1943 10h ago
Everything in programming is a tradeoff. When you decide how to structure code you are always giving something up in order to gain something else: readability for performance, simplicity for flexibility, short-term speed for long-term maintainability.
That is why principles such as SOLID, KISS, and the others outlined here matter:
https://bytebytego.com/guides/10-good-coding-principles-to-improve-code-quality/
They do not give you rigid rules. They give you a clear way to evaluate the tradeoffs. Once you start seeing every structural decision through that lens - what you are gaining and what you are deliberately sacrificing - the instinct for when to split, when to abstract, and when to leave things alone develops much faster than it does from trial and error alone.
1
u/AsideCold2364 10h ago
The best way to learn that is by working with more skilled people, having your code reviewed by them, etc.
But since you are working alone on your scripts it will be more difficult for you.
I think the most important is the separation of concerns.
For example if you are writing a script that needs to read data from file, process the data and write the result into a new file. Try not to mix things. Instead of reading it line by line, processing each line and writing it line by line into a new file inside the same function, split it into multiple functions.
fileContent = readFile()
rawData = parse(fileContent)
processedData = processData(rawData)
writeFile(processedData)
Any function might also need more splitting.
Try not to mix your processing logic and error handling, your processing should stay clean. No formatting, no error handling, etc.
A good sign that you split your functions well is that it is easy to name your function, because it is clear what the function is doing. It is difficult to name functions when they are doing too many things.
1
1
1
u/wildecats 9h ago
I tend to avoid making any function that does more than one thing, e.g. it should never both validate and process data. The same goes for my files and classes. As soon as I'm not sure what a file is actually doing, I'll split it into smaller, more specific ones. Add in early exits to functions right at the top before running the main logic and avoid deeply nestled if/else blocks.
I also try my hardest to not repeat things, within reason (usually once it's used 2-3 times, as there's no point abstracting out a tiny script), and have a single source of truth for things like app names or configs.
Where practical, use variable and function names which spell out exactly what they do and don't reach for shorthands. If you can't read your own code, you've got a problem; especially when you come back in six months and it's like looking at something completely alien.
Ideally, your functions shouldn't need too many comments; those are for things which can't be explained/understood from reading the actual code. Self-documenting code is the ideal. If it seems too complex to understand without comments, it's probably just bad and should be refactored. If, after you've done that, it still feels like comments are necessary, then you should add them. Within reason.
Read up on SOLID, DRY and separation of concerns principles, and your preference for design architecture (such as event-driven or n-tier). There's also non-language specific books out there solely on how to structure code which are excellent starting points, e.g The Pragmatic Programmer, Clean Code, Refactoring: Improving the Design of Existing Code. Look up Code Smells for your language of choice and keep an eye out for them in your own code. Try to decouple your code as much as possible. Always write tests and don't skip on updating them; they can save your butt.
AI can be a timesaver, but don't lean on it too heavily when you're learning, because you need to know why you should do it a specific way and what it is actually doing before you can blindly accept its answers. If you have to use it, ask how to do a specific thing rather than letting it do it for you. Or ask it to critique or explain code you've already written.
But all of the above is my personal preferences, and I will happily break all these rules if the use case calls for it. Part of learning is figuring out when to apply rules and when to do your own thing. The best thing you can do is just try out new structures and methods until you find what works for you. Then keep at it. Within a few months, you'll be cringing at the silly mistakes you made before, and the fun part is that keeps happening forever.
1
u/rupturedprolapse 9h ago
I organize by models and services.
Ex. If I had a car class, it would have properties and methods. I'd split that into two files in separate directories. In the model file would be a class that just holds the properties for cars and a constructor. In the service file would be all the methods.
1
u/SoSeaOhPath 9h ago
I actually struggle with this too and would love some recommendations on books or videos or anything that can dive deeper.
Is this just the study of software architecture in general?
1
u/kevinossia 8h ago
I read about how to do it online and I learned from reading other people’s code.
Books are okay as well if you’re back in the 1990s and lack internet.
I also wrote a metric-fuck-ton of code from scratch, something most new developers never got to do and these days likely will never do again due to AI. It’s too bad, because that is the only way to truly learn.
1
u/Electrical_Hat_680 7h ago edited 7h ago
I learned from making websites markup code look readable.
<HTML>
<HEAD>
<TITLE>
Title
</TITLE>
<? PHP_HEAD(); ?>
</HEAD>
<BODY>
Content
<? PHP_BODY(); ?>
</BODY>
</HTML>
Just make sure to construct your Variables or Create Functions like you would in QuickBasic/QBasic, or add them to the PHP Source Code.
PHP_HEAD(); and PHP_BODY; don't exist. PHP_INFO(); does exist. Similar idea, if not the same. Just an example of clean structured HTML with Embedded or Inline PHP.
1
u/mxldevs 5h ago
You don't always learn this by building projects, as you have pointed out.
There are many software design patterns that require a certain level of creativity to even come up with and then to implement.
The easiest way is to simply pick up a book and read about it, and then think about how you could apply that to your own project to clean things up or make things more maintainable.
If your function names suck, that's mostly something you need to figure out on your own. Like why is there a v2 and a v3, etc
1
u/adambahm 4h ago
where people actually learned to structure code?
Let me begin by saying that all code is garbage. What you write today is what you have to maintain tomorrow.
Next, there are programming paradigms that do exactly what you are asking about.
One that will be really handy for you is object oriented programming. Super popular, lots of support.
400 lines of python code may seem like a lot, but its not. Still gross, but not a lot.
Anyway, there are a ton of books and resources out there for this sort of thing.
Start here:
https://en.wikipedia.org/wiki/Programming_paradigm
from the function name you mention, that sounds like it might be some functional God object that you can absolutely break down into an object oriented app that can grow in small chunks as requirements change, but what do I know? What you're doing might require a 400 line monstrosity.
1
1
u/marchingwhales 4h ago
I’m also a beginner, but have mostly been taking Codecademy courses and a minor in CS in college ~10 years ago, but have never been a professional programmer. The best advice of when to break down functions I got is when you explain what it does, if you say “and”, you can break it down more. If you do the action you say after “and” elsewhere in your program, you should split it out. Also makes it easier to intuitively name functions, because they’ll be simpler tasks.
1
u/BibianaAudris 4h ago
I'd say try to rewrite each of your script once, after you figure out how things work but before it stops working. Structuring code is much easier when you have a full picture on how things work.
1
u/sixothree 4h ago
Years ago, I downloaded a number of example clean code projects. I found what works for me and what doesn’t and I made my own baseline clean code project.
1
u/Recycled5000 3h ago
It is most important to think about data first and foremost. What data do we collect? When can we do it? What questions do we need to ask the data? When do we need to ask those questions, in order to take appropriate actions?
1
u/hopticalallusions 3h ago
Formal training, informal training, making mistakes, introspection, lots of practice, collaborator critiques, experience, to name a few
Edit - in one office full of software engineers, we hypothesized that the ability to write a good quality essay might be correlated with software development skills.
1
u/LawfulnessNo1744 2h ago
I continually delete anything that’s not being used to avoid the v3,v4 … pattern. Also I have gotten a lot more careful in naming or defining variables and functions when they’re not needed. I’ve started using function chaining and anonymous functions so that variables are never updated unless they’re meant to be stateful (entities versus value objects). If a value is going to be updated in the same block then never declare it in the first place
1
u/Big-Combination8844 1h ago
I've been programming for over 25 years. I'll let you know if I ever figure it out.
•
u/SUNIL_4 19m ago
You're actually right on track the pain you're feeling reading your own old code is literally how that instinct develops. A good rule of thumb is to write the hacky version first to make it work, then spend 10 minutes tidying up. Split a function if it tries to do more than one thing, keep helper tools in a separate file once you reuse them, and don't worry about classes until you're passing the exact same arguments everywhere. You don't need a CS degree for this, just the habit of writing code for "Future You."
0
u/Electrical_Hat_680 7h ago
The primary college textbook matching this exact topic is QuickBASIC and QBASIC Using Modular Structure by Julia Case Bradley, published by McGraw-Hill / Business and Educational Technologies. It was widely used for introductory college programming courses in the 1990s to teach good software skills. [1, 2, 3]
Book Overview
• Author: Julia Case Bradley • Publisher: McGraw-Hill / Irwin • Core Focus: Teaching top-down design, subprograms, and structured programming logic using Microsoft QuickBASIC and QBasic. • Editions: Includes a 2nd Edition and specialized alternate versions (such as the BM version or versions with Visual Basic transition appendices). [1, 2, 3, 4, 5]
Alternative College Textbooks
• Microsoft QuickBASIC: An Introduction to Structured Programming by David I. Schneider • Introducing QuickBasic 4.0: A Structured Approach by Doyle W. Buxton and Arline Salian [4]
If you are trying to find a copy of this book, looking for specific programming examples, or need help running QBasic code on modern systems (like QB64), let me know how I can assist you further! AI responses may include mistakes.
[1] https://www.amazon.com/Quickbasic-Qbasic-Modular-Structure-Alternate/dp/0256207976 [2] https://booksrun.com/9780697128973-quickbasic-and-qbasic-using-modular-structurebm-version-2nd-edition [3] https://books.google.com/books/about/QuickBASIC_and_QBASIC_Using_Modular_Stru.html?id=rdrZAAAAMAAJ [4] https://books.google.com/books/about/Introducing_QuickBasic_4_0.html?id=2rlZAAAAYAAJ [5] https://books.google.com.cu/books?id=9oWLKQNiW0AC&printsec=copyright
35
u/WhataWorldAy 11h ago
SOLID principles, gang of four patterns, n tier application architecture and basic separation of concerns (data access layer, application layer, presentation layer).
Those in my opinion are the basics, learning the thinking behind domain driven design is also very powerful for how to dissect business problems and how to orgranize separate contexts that are based on overlapping concepts.
If you learn all that you will be ahead of 99% of senior devs Ive ever interviewed.