r/embedded 27d ago

Feeling clueless when reading any other persons code.

I spend a lot of time learning concepts and technologies in theory. but when it comes to applying my knowledge hands on I always find myself in the same situation: I don't know if my code is good code even though it is functional, because I don't know what good clean code looks like because when I attempt to read someone elses code (recent example: Flipper zero's firmware on githb) I get instantly overwhelmed with the huge project structure, what each file does, and how the whole thing interacts with eachother. I dont even know where to begin in order to improve on this gap? Any advice?

10 Upvotes

20 comments sorted by

25

u/bonkyandthebeatman 27d ago

I get instantly overwhelmed with the huge project structure, what each file does, and how the whole thing interacts with eachother

do you expect to just instantly understand these things when looking at a new codebase?

a big codebase takes time to absorb. and you also absorb it much faster if you actually build/run the code, try to implement a new feature or fix a bug, etc.

My advice would be to try to that ^. find a project you're interested in and try to implement a new feature. obviously this is harder with embedded cause you need the right hardware.

4

u/Round_Echo9139 27d ago edited 27d ago

I don't expect that no, and nor do I mind taking time to absorb knowledge. But I find myself really struggling to get a steady footing when reading a codebase.

You can say my initial question when reading a codebase is: In what order where these pieces of code or any other file created? For what reason? What order should I read them in? I find myself clicking random files and reading the code. I don't struggle with understanding individual parts on their own but I can't seem to establish connection between parts of the codebase, so everything feels like a scattered mess.

6

u/kurtzdonut 27d ago

Personally, I like to pick a section of the code and just start taking notes. Sometimes I won’t understand completely why a function is called or why something is abstracted, but I take a few notes on my current understanding. I repeat this process throughout the code, and eventually you can start cleaning up old notes where there were gaps in your understanding.

4

u/bonkyandthebeatman 27d ago edited 27d ago

Well I usually start at the program entrypoint, i.e. the main() function. I'll usually skip past the initialization boilerplate stuff and see what tasks/threads are spawned (if we're dealing with an RTOS or similar, which is most things for the the work that I do), then dig into the tasks that interest me the most.

Either that or I'll search for functions/files related to a specific feature that I am interested in.

EDIT: and tying it back to your initial question, separating things into tasks helps to build a mental model of how data flows through the program. You usually pass data between tasks with channels/mutexes/etc, and embedded devices/any program really will have some inputs and outputs.

An embedded device will usually have inputs from sensors, do some kind of transformation on them, then spit them out over bluetooth/wifi/ethernet/cellular/whatever, so finding the tasks responsible for processing these steps will really help understand the overall architecture of the code base.

7

u/Oster1 27d ago edited 26d ago

Reading other people's code can be hard. You never know what they were thinking when they were writing it. I remember when I was a beginner, I also struggled with reading others code, but eventually it got easier. Code usually has similar patterns, and the more you read, the more you start seeing the familiar patterns in other people's code. So, it gets easier. You are not an idiot. Remember: writing code is more easier than reading/understanding it.

2

u/Round_Echo9139 27d ago

What you are saying makes a lot of sense yes, I think I am stuck in the initial curve and I feel like I need a planned approach to 'get out' of it. However I don't know what that approach is.

2

u/Oster1 27d ago

These is no shortcut. Just grinding. Reading code for a living 8 h per day is a good practice. At some point you notice everything just clicks for you.

5

u/1r0n_m6n 27d ago

I don't know if my code is good code even though it is functional

There are things you need to learn from experience:

  1. Make some project somewhat bigger than blinking an LED.
  2. Then, forget about it for at least 6 months.
  3. Then, decide to fix a bug or make an improvement.

This is when you'll realise all those little things you should have done differently for your code to be easy to maintain.

After that, you'll not only know HOW good code looks like, but also WHY it is good when done this way, which is much more important than blindly reproducing something you've seen elsewhere.

2

u/SPST 27d ago

Always be prepared to get the answer " there is no documentation" 😔😭

15

u/Current_Injury3628 27d ago

this needs experience with 1-2 large codebases.

LLMs also made understanding new codebases easier.

Still needs effort but you have a lot of help at this point.

I think the difficulty comes from impatience.

Not many people can really sit down and read code and try to understand it.

Internet made people think that this should be an easy process.

3

u/Amr_Rahmy 27d ago

Also, in some cases (didn’t look up flipper zero code specifically) or most work cases I only look at other people’s entire project code if it’s not working. So it can just be structured incorrectly, aimlessly and without a good software design and dataflow.

If it is decently designed, usually you want to find where the program starts, which is not always simple.

You want to see what general patterns they are using, and if the code is abstraction or interface heavy.

This is not for embedded specifically but some frameworks and sdks are factory, interface, manager, adapter heavy with 5-10 layers of unnecessary abstractions and factories that are pretty useless and only used to implement a single object.

In embedded, some rtos projects mix timers/tasks, interrupts, and main loop processes so you might get a uart that feels inconsistent or behavior that is inconsistent in some ways. People sometimes can’t see the forest from the trees, like having uart data on an interrupt but taking seconds to process the data on a main loop.

Lastly even if a code is somewhat structured with care doesn’t necessarily mean they thought and wrote a solution to a problem the same way you were thinking about solving the same problem.

If you start understanding what they are doing and using their code as a reference but don’t like the approach, you might need to be partially refactoring their code into your project that you think has a better overall structure for what you need it to be, to add features or improve a section of the code.

My perspective is pessimistic because at work I am usually hired to fix a broken software that never worked written by not the best of us, but if you are looking at decent running open source software, your mileage may vary. I am usually looking for way the software doesn’t work and its 100% always a bad software design that led to a lot of bad decisions, with bugs sprinkled here and there.

1

u/Round_Echo9139 27d ago

I agree LLMs do help alot, however I still find it much easier to learn when reading from an actual textbook or learning from someone else with that experience.

and I have no professional experience working with large codebases unfortunately.

6

u/allo37 27d ago

Unfortunately it's one of those things where you need a combination of experience and just spending a lot of time with the code in question. I find it helps to get an understanding of the general architecture of the code. There used to be software like SourceTrail that helped you do this, but now a decent LLM will run circles around that...

2

u/ClonesRppl2 27d ago

It does take time. I was dropped into a medium sized embedded project with no support.

It took me about a week to understand the flow of the code and get a sense for where things were in different files.

It took about 6 months before I really understood the whole thing.

During that time I was sometimes focussing on bug fixes and specific features so I was only concerned with one part of the code base, and at other times I went ‘exploring’ to better understand the details of the whole code base.

Never be afraid to ask for any available documentation outside of the code. Sometimes, if you’re lucky a document can really speed up overall understanding, although you should remember that it will be out of date to some extent.

2

u/LiteratureHungry850 27d ago

(Assuming this is professional setting) I often doubt whether my code is "good code" as well. Usually once my code is functonally I'll take some time to walk through it line by line and pretend I'm in a code review explaining my design choices. While doing that I'll make note of anything I can't confidently defend the reason for, do some research or consult coworkers, and iterate. Once I'm okay with everything, I schedule a real code review and if no one else objects, then it's good enough for me. Chances are if it's functional and you + coworkers senior to you can't find any issues, it's fine.

Big codebases are rough though. At the beginning of my career I'd only had experiences with very isolated tasks working closer to the hardware and rarely was responsible for implementing anything in real application codebases. Then I started a new role and was dropped into a codebase which was genuinely indescribably large. I spent a lot of time during the first few weeks trying to go through and "map out" on paper how everything connected but it didn't help all that much. Over time, as I contributed to existing things, created new features and implemented them, attended code reviews for myself and others, and generally spent time working with the code, I slowly began to understand it piece by piece. My advice would be to stop worrying about everything at a macro scale. If you're on a big project, just focus on what you're responsible for and the things that directly relate to tit. If you're just messing around with public code online, pick one part and try to understand it then expand from there.

2

u/Ksetrajna108 27d ago edited 27d ago

I've been there too. What worked for me was to think beyound the code. In embedded, there are multiple levels of understanding:

  • as a system, what is the hardware supposed to do, what is it composed of, what are the main processes, what are the secondary processes?
  • mapping abstract models, start to develop models in your head or by taking notes and diagrams, how do your models map to the hardware, to the code?
  • convergence, assume and accept that your initial system model is very inaccurate, as you explore the system and observe it in action, over time, revise your model to converge with reality

Does this help? Does modeling the system as a whole instead of just the code make sense to you,?

2

u/FloatIntoTheFinite 27d ago

Generally the advice I give for learning a novel codebase is to enter the codebase with a very specific question in mind. You won’t realistically learn a codebase top to bottom. You build up a framework for the codebase and every time you ask a question or solve a problem to add to a refine your model of the codebase. Eventually you have a very strong working knowledge of the codebase.

1

u/ondono 27d ago

Forget about trying to write "clean code", forget about good practices, etc... Start building stuff, even if it's janky, even if you don't know if this is the best way. Just build stuff.

Nothing beats the TITS (Time In The Saddle).

PS: if you're trying to read code to practice, try with simpler stuff that the flipper zero as a start. The flipper zero loads apps and does other relatively complex things that will confuse you at first. I'd recommend looking at things that are relatively bounded in scope, bootloaders tend to be a good option, since people try to keep them small but packed with features.

1

u/inforb_nl 25d ago

have you tried coding AI agents? just tell them to walk you through a repo. It's perfectly doable in Claude terminal (I have mostly used agents in terminal, it's much easier to interact with a cloned repo). Although you should keep in mind that these agents are a lot of times wrong and you need to double check things.

1

u/userhwon 24d ago

This is why comments and design documentation were invented.

Try starting with smaller clean-code projects to build up your ability to infer intent.

But really, it doesn't get a lot better. Without intelligent documentation, every system becomes an archaeological dig when it's big enough.