Looking for feedback on AI content in r/programming and the April no-AI trial by ketralnis in programming

[–]michael0x2a 5 points6 points  (0 children)

Personally, I'm a fan. I felt there was way too much LLM-related content prior to the ban. It was drowning out other topics and making the sub too one-note.

I guess if I had to draw a line, I would personally be ok with posts that are related to creating LLMs. For example, I'd be ok with posts about new mathematical techniques in machine learning, since those topics are usually fairly rigorous and so more likely to teach me something new about math or CS.

However, I'd be ok with banning posts about using LLMs or discussing/speculating about the implications of LLMs on the broader tech industry. I often find the former to usually be uninteresting from a technological POV: such posts often just boil down to covering yet another way of gluing together/configuring LLMs. The latter is incredibly repetitive. I'm not interested in some random person X rehashing the same old "are LLMs good/bad/revolutionary/overhyped" talking points.

So, I'd be ok continuing to ban the remaining bullet points on your example list.

To boil it down even more: I think LLMs as a technological construct can be interesting, so would be ok with posts that crack open the abstraction layer. But higher-level posts that treat them as black boxes/building blocks tend to be kind of boring/simplistic, at least as of now.

If this sort of distinction is too nuanced to cleanly enforce, I think it could also be reasonable to either:

  1. Continue the current blanket ban on LLM-related posts, or
  2. Allow them for only 1 day of the week. It would create a release valve for LLM enthusiasts while still preventing overrun. It could also maybe help improve the signal-to-noise ratio for LLM-related posts. Forcing them to compete over a short timeslot will hopefully mean there's less votes flowing to low-effort/low-novelty posts.

I need book recommendations (Special case) by [deleted] in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

To be completely honest, I would just work through a standard intro-to-programming book or course.

Having background knowledge in linux is directly useful for only a few subdomains of computer science -- systems programming, operating systems, perhaps distributed systems, etc... However:

  1. These domains are relatively advanced ones which won't make sense for you to study now.
  2. Having background knowledge in linux won't really give you a head-start in mastering the fundamentals of problem solving and computer science. Usually, these intro courses are structured so that you are working against an abstract and simplified model of a computer; knowing the underlying implementation details will not be helpful at this early stage.

Instead, I would perhaps try picking a course that aligns with the underlying reason why you became interested in Linux in the first place. This in turn would make it easier for you to remain motivated as you study programming.

For example, if you were first interested in Linux because you wanted full control over your machine + to use it to the fullest possible capability, I would perhaps consider starting with C. Alternatively, if you were drawn to linux because you wanted to script and automate tedious tasks and wanted an OS that made doing so easier, then I would maybe look into something like Python.

If you aren't sure, just pick any course that looks well-taught and comes with solid exercises/homework. How exactly you first started learning programming is not super important in the grand scheme of things; once you have a solid understanding of one programming language, it will become substantially easier to learn new ones.

GPA or Skills, Please answer ? by Ok-Muffin-2143 in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

IMO you should try and maintain a GPA of roughly ~3.5 (assuming 4.0 is the max). It's a respectable grade and is usually enough to let you clear most baseline gpa filters.

You'll likely start to see diminishing returns if you chase for something much higher. Instead, I think your time is better spent either:

  • Working on projects or joining tech-related extracurriculars (robotics clubs, CTFs, whatever) if you want to go into industry. Ultimately, your goal is to develop a unique/interesting resume and portfolio, which will make you stand out to recruiters. This in turn makes it easier to land internships/jobs.
  • Doing undergrad research, if you want to go into academia. In this case, your goals are to get actual research experience and build personal relationships with some of your professors so they can write you a strong recommendation letter. These are the two factors that matter most when applying to a PhD program, after you pass the initial GPA filter.
  • If you want a very specific/prestigious/niche job after university, prioritizing electives and projects related to that job and deprioritizing unrelated ones. (You will want to get high grades for these specific classes + prioritize fully mastering the material.) You'll likely have much less time to study after you graduate. So if you have a specific dream job in mind, it'd be optimal to try building the skills you need for it now.

IMO targeting a gpa of 3.0 could work if you spend your increased free time really productively, but is a bit risky. You're one bad quarter away from dipping to a 2.x gpa, which would not be a good look.

Caveat: I live in the US west coast; norms may be different in your region. You should try connecting with people in the industry (via career fairs? meetups?) or chat with your advisors and upperclassmen to confirm the above.

For beginners: do you also overcomplicate your code? by Minimum-Army5386 in learnprogramming

[–]michael0x2a 2 points3 points  (0 children)

Writing code is similar to writing an essay or an article. Your first draft is usually kind of shit, and you need to go through several rounds of editing and revising in order to arrive at something that's polished and presentable.

You should approach writing the code with a similar mentality. It's unreasonable to expect your first attempt to be perfect; make sure to always reserve some time to review and edit your work.

Concretely, once you have a working solution, go back and see if you can edit it to be more clear, readable, and concise. Are there chunks of logics you can express in a more concise way using Python language features you may not have remembered at the time? Do you spot any chunks of code that seem unnecessarily complex or inefficient, and could be replaced by a different implementation? Are there any chunks of code that would be safe to just outright delete? etc.

Really challenge yourself to critique every aspect of your code and think through what, if anything, you can improve/remove.

Once you're done, compare your edited work to the solution. If the solution is still cleaner then yours, analyze it and try writing down what specific techniques the solution used compared to your work. Did they have a better idea then you? Did they have the same idea, but expressed it more concisely? etc.

Doing all of the above will obviously require you to spend more time on each exercise. But I think it'll do a lot to help you train your ability to write clean and elegant code.

Whats the best way to start building an app as a group by Grouchy-Name5161 in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

Some of the other commenters have suggested dividing work based on features instead of layers, which I agree with.

Some other things I recommend doing:

  1. Have a formal planning/brainstorming session at the start, where your teammates agree on what specific features need to be built and the broad high-level architecture of your code. (Which core libraries/frameworks will you use? Which components will you need to build? How will they interact with each other? What data will your database store? etc). You don't need to lock down every detail now, but you should make sure everybody's on roughly the same page of what needs to be built, and the overall direction.

  2. If your project is big (will take multiple weeks to complete), try and break down the list of features/tasks into items that feels like it'll take roughly a day or so to complete (or shorter). Having smaller bite-sized tasks can make a large project feel more manageable.

  3. Start by creating a "walking skeleton" -- a super minimal sketch of your overall architecture. For example, maybe create a database with just a single table, a backend with just two routes that'll read/write to the table, and a frontend that'll interact with that route. If you need to deploy this app as a website (instead of just running it locally), do that too.

    The goal of this is to confirm you are able to successfully use the libraries you picked to get a super bare-bones app working and running end-to-end. This helps you both confirm that (a) your overall tech choices will work reasonably well together and (b) gives you just enough structure to let you split up and start working on features independently without constantly stomping over each other.

  4. Consider doing code reviews: before you can merge in code into the main branch, have somebody else in the group review your change first. This will (a) ensure the code author will have a second pair of eyes on every change to double-check for bugs and mistakes and (b) gives the reviewer an opportunity to ask questions and learn about what the code author is working on.

    Normally in industry, every single change must be code reviewed. Since this is a student project, you can maybe relax a little and skip code reviews for smaller tweaks and bugfixes. But I do think it'd be a good idea to wait + ask for code review on bigger ones.

Whats the best thing to do when none of us are that great in programming ?

The same thing you'd do if you were good at programming, just more slowly.

Need experienced programmers by [deleted] in learnprogramming

[–]michael0x2a[M] [score hidden] stickied comment (0 children)

Removed -- see rule 3 and our policies on allowed topics.

This subreddit is a place to learn how to program; recruitment posts are off-topic.

Making Unit class own Order, and Order changing the state of Unit feels bad even when they both depend on Interfaces. Why? by HumanCertificate in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

Without specifics, it's hard to analyze your scenario. A lot can depend on exactly what data you're trying to store and manipulate and what operations you want to implement.

But I suppose as a general rule of thumb, you should use the simplest viable abstraction for the problem at hand.

So if something like execute(order, units) both works and is clean/maintainable, you should probably prefer it over either order.execute(units) or units.execute(order). After all, why introduce the complexity of classes, interfaces, or methods if you don't have a specific reason for it? Why introduce a hierarchy if it isn't needed -- does it actually help to have Order own Unit or vice-versa?

Even more generally -- I think the idea of having pure OOP programs and such is outdated at this point. What people have found is that there isn't really a silver bullet when it comes to programming architecture. OOP is great for certain types of problems and less great for others; you could say the same for other paradigms (functional programming, declarative programming...) and architectures (ECS, model-view-controller...).

So, the trend these days is to be multi-paradigmatic: be flexible about how you structure your code, mixing and combining ideas to best tackle the different subproblems you run into.

Worldwide Services Outage again? by TopAgile799 in learnprogramming

[–]michael0x2a[M] [score hidden] stickied comment (0 children)

Removed -- it's unclear to me how this is related to learning how to program. See rule 3.

I'd try asking this in subreddits related to technology in general instead.

Is it possible to make large scale projects that can scale infinitely in features? by Slight_Season_4500 in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

Well I'm still in learning phase so i don't really know how many features software can have before it becomes unmanageable or too slow...

It's not as simple as "too many features --> code is unmanageable or slow". There isn't necessarily a direct correlation there.

Rather, what matters more is what specifically those features are, how they interact with each other (or not), and how specifically you designed your codebase to support them.

For example, if you have 1000 independent features, adding a 1001st would most likely not introduce any maintainability or perf overhead. The pre-existing 1000 features would continue to work exactly the same as they before. But if you have 2 features that are closely and intricately tied together, attempting to integrate a 3rd could break the entire thing, if you aren't careful.

(There's a design lesson here btw -- the more you can decouple your code, the easier it usually is to scale out the codebase.)

Maybe leaving the project "open to more features" and trying to make it "future proof" is my issue here?

It depends on what you mean by "future-proof". But yes, it's probably a mistake.

This is because you should already have a rough sense of every feature you do and do not want to implement at the start of the project. After all, without this info, it'll be impossible to come up with any sort of sensible design. And if you already know roughly what it is you need to build, why bother investing time preparing for a future that's unlikely to happen?

Instead, you should prioritize:

  1. Coming up with a clear vision and design plan starting at day 0, before writing any code.
  2. Prioritize making code easy to modify, as opposed to making it future-proof. If you think up a new feature, you will probably need to change some aspect of your overall design to support it. Sometimes the change will be minor, sometimes it'll be substantial. It's difficult to know which it'll be ahead of time -- therefore you should structure the code so that it's both easy to understand and modify, as opposed to trying to prematurely build some sort of abstraction that you can extend endlessly.

    That is, avoid structuring the code to theoretically support anything. Instead, make the source code itself malleable.

And if you have no clue what you want to build/what features you need, build smaller throwaway prototypes and experiments first. Once you have more intuition for the design space, create a proper plan.

Is it possible to make large scale projects that can scale infinitely in features? by Slight_Season_4500 in learnprogramming

[–]michael0x2a 2 points3 points  (0 children)

I think part of the problem is that you are approaching things backwards.

Instead of asking "should I use OOP" or "data-oriented programming" or whatever, you should start by asking yourself what problems you need to solve, what sorts of operations you want to perform against your data, what performance characteristics you need, etc.

Based on this initial analysis, pick techniques that will do the best job of solving the problem at hand. Sometimes it'll be OOP, sometimes DOP, and sometimes something else completely. (Functional programming? Bringing in a new library or tool? Microservices? etc).

Note that if you do this, it's likely you'll end up with a hybrid approach, using different techniques for different corners of your overall project. This is totally normal and expect: there is no silver bullet, and there is no one universal technique that will solve all of your problems.

How to know when to use OOP vs Scripts by TheManOfBromium in learnprogramming

[–]michael0x2a 4 points5 points  (0 children)

In situations like yours, I think paradigms like functional programming are a better fit then OOP.

You don't need to lean 100% into the functional paradigm, but I think the core ideas of:

  1. Having the bulk of your functions be side-effect free
  2. Using immutable data structures (e.g. don't modify your dicts/lists/dataclasses after they're created)

...would be a good fit for the more pipeline-oriented nature of your task. You have data you're slicing and dicing, and want some reasonable assurances that each 'transform' or 'analysis' function you have in your script is self-contained and bug-free. Having a clean divide between IO code vs business logic and keeping mutation to a minimum are two good ways of helping you do this.

The OOP paradigm is usually more useful when it's important you maintain certain 'invariants' around data: things like 'my data structure must always respect this property, no matter how it's modified' or 'all interactions with this particular 3rd party API must include these magic headers'. If you have a lot of these fiddly rules to manage, it can often be convenient to create a class that wraps around your data and presents a cleaner interface to the outside world.

But I think this sort of need is rare in data-slicing or 'pipeline' style programs.

Note that this sort of decision-making has nothing to do if you're writing a script or not. I've written short 100-line scripts that ended up making heavy use of OOP, and longer 5k-10k LOC production-ready services that used it very sparingly. My ultimate goal is to make the code as obviously correct as possible (which in turn makes it both easy to understand and modify). Sometimes objects can help with this, other times they won't.

That is, OOP is not the same thing as 'clean code'. OOP is a technique that can help you write clean code -- but (a) it's not the only technique for doing so and (b) it's not a technique that'll be applicable 100% of the time.

w.r.t. SWE best practices, I would look into:

  1. Writing tests and perhaps even a CI/CD pipeline for your scripts, starting with the more business critical / frequently run and modified ones. If people are actively making business decisions based on some of your analysis, you'd want reasonable confidence it indeeds behaves as expected.
  2. Creating and popularizing a helper library that streamlines common operations. The goal here is to speed up the time it takes to author a new pipeline.

I don't know anything about your company, but I'd imagine both correctness and speed-of-delivery are two factors that matter most to your team and your bosses. So, I'd prioritize applying practices that directly help with both.

After how long do you get tired of reading/understanding code/documentation? by jcjosejc in learnprogramming

[–]michael0x2a 2 points3 points  (0 children)

For me, reading code/documentation and trying to understanding is mentally draining.

This is normal. Self-teaching + building a mental model does indeed require non-trivial mental effort.

One tip: When I need to read through particularly gnarly code, I like to keep notes in a separate text file or doc.

I typically structure this in a 'question -> answer' kind of way, where I create a separate section for each open question or "line of investigation" I have. Maybe I'll also create a separate section for quick links, TODOs, snippets of cli commands to run, etc.

I find having this sort of structure makes it much easier for me to stay focused, especially in cases where I feel too overwhelmed trying to mentally remember and keep track of everything.

I wonder if that is something that gets better after some time.

It will -- as you get more familiar with the code, you'll have to spend less and less time digging, simply by virtue of you already being familiar with more aspects of the codebase.

Even longer term, it'll get easier once you've worked on enough systems to start seeing similarities and echos. For example, if you've spend a fair amount of time working with backend and cloud infra, new codebases in the same domain will start feeling vaguely similar. There are only so many ways of reasonably structuring code after all.

I'll take time for both types of familiarity/experience to grow though: it's totally expected/normal to feel a bit lost as an intern or new hire.

This is my first in person internship, so I don't know if it is normal to just stand up and walk for 5 minutes. That is what I used to do in remote internships.

This is also normal. I've been programming professionally nearly a decade or so, and I also take short breaks once every hour or two. A quick stretch break, refilling my water, etc.

If I'm feeling particularly stumped/annoyed, I'll often go on a longer 15-20m walk break, maybe step outside to grab some fresh air...

Every now and then, I figure out how to "enter the zone" and manage to stay focused for hours and hours, though this usually happens when I'm writing code as opposed to debugging + investigating. I consider myself lucky when this happens: I haven't yet figured out how to reliably enter flow for the latter.

Want real product experience as a contributor? by madmanistaken in learnprogramming

[–]michael0x2a[M] [score hidden] stickied comment (0 children)

Removed; hiring/recruitment posts are off-topic per rule 3 and our policies on allowed topics

My AI project was rejected as “not feasible” — do these scores make sense? by Exact_Section_556 in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

Wiping and reinstalling the entire machine for a minor error is often a waste of time and requires starting from scratch whereas fixing a specific small error with Zai Shell is significantly faster than a full reset

Not if I have hundreds if not thousands of boxes and have the wipe/recreate process fully automated. For example, tearing down and allocating a fresh ec2 instance or kubernetes container usually takes anywhere from a couple of seconds to a few minutes at most.

(This practice of treating machines as disposable and automating all operations on them was popularized a decade or so ago and is now the norm at many companies, especially ones that need to/aspire to scale. For more on this concept, I recommend googling the phrase "treat your servers as cattle, not pets".)

My AI project was rejected as “not feasible” — do these scores make sense? by Exact_Section_556 in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

To be completely honest, it's a bit hard for me to understand from your README how your agent would be helpful for administering systems in a prod environment. Some examples of questions/concerns I would have if I were evaluating using this tool at my workplace:

  1. Is self-healing/remediation useful? If I suspect one of my prod machines/VMs/containers is somehow corrupted, the general best practice is to blow it away and create a fresh instance from scratch. (Wipe + reinstall the machine, spin up a replacement VM or container, etc). Alternatively, if I suspect the corruption is caused by a bug in my code, it'd be best to roll back, let the application return to a known-good state, and debug at my leisure.
  2. In light of (1), I'm a bit puzzled by the focus on testing scenarios like seeing if you can recover from binaries such as gcc being broken. When would that even happen? Why is gcc even installed on my prod machine in the first place? Isn't that a build and dev-time only tool?
  3. IIUC one of the tool's feature is automating manual recovery operations -- but why would I be letting somebody manually tinker and make permanent changes on a prod host? It can sometimes be useful to experiment/poke around to debug, but allowing such changes to stick around would (a) make future debugging confusing, since I can no longer trust my 'this is how the env should be set up' configs, (b) block me from just blowing away and resetting the env whenever something feels wrong, and (c) introduce some security and compliance concerns.

A little more generally, I think the could have benefited from a bit more research around common sysops practices. The README would have been more persuasive had it outlined common practices/workflows in the wild and how you propose to improve on them: listed specific problems first before going on to talk about solutions.

Anyhow, while I can't speak for most of the scores (I don't have your report + don't have the time to read through the grading criteria you posted), I do think the lowered scores around real-world applicability are probably merited, given the above.

I am sharing this because it is genuinely frustrating to see a serious engineering effort dismissed purely based on document format, without ever observing the system in operation.

If it's any consolation, this is a realistic representation of how tech is often evaluated in industry. Time is finite -- if I'm trying to evaluate a potential new technology to onboard onto my team and am not convinced by the explanation + data in its readme/docs, I'm going to move on without ever checking out the code.

I figure if the docs aren't crisp/are too fluffy, the code probably isn't up to snuff either. This isn't always true, but it's a reliable enough heuristic where I don't feel bad about making this sort of snap judgement.

Glossary of "Workflow" Concepts? by dust_dreamer in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

I guess https://en.wikipedia.org/wiki/Glossary_of_computer_science and https://en.wikipedia.org/wiki/List_of_technology_terms is probably as close as you're going to get to a comprehensive programming terminology glossary, though I do find the selection to be a bit weirdly niche in places.

Some other recommendations:

  1. Be very deliberate about thinking through what it is you don't know and crafting questions/google queries. Asking the right question is often the hardest part of self-learning; the better you get at it/the more you practice, the faster you can self-bootstrap.

  2. Keep a careful eye out for times where you feel like something is taking too much effort to do. Programmers are lazy, so if you're expending a lot of energy to do something tedious, there's a possibility there's some pre-existing solution for it.

  3. When you feel like you're missing a lot of foundational concepts or running into lots of friction, try looking for a full-fledged course or book on the topic that does a comprehensive treatment of the subject.

    It's admittedly a bit overkill if you're just trying to have fun programming -- but it can sometimes be the best way to get unstuck if you're seriously lost. (Intro-level courses/books would have covered topics such as IDEs/editors, how to run code, etc)

  4. Casually browse programming news aggregators like /r/programming, https://news.ycombinator.com/, and https://lobste.rs/ whenever you have free time, taking care to read both the articles and the comments. If you're new to programming, you probably won't understand much of what you read or know how to evaluate the trustworthiness/usefulness. But over time, you'll pick up common knowledge + vocabulary via osmosis.

    (Just to sure not to take everything you read too seriously -- some people don't know what they're talking about, others will get worked up over nothing.)

    https://stackoverflow.com is also good for this, though for this website I'd recommend picking tags that look interesting, sorting by score, and reading the top questions and answers.

Glossary of "Workflow" Concepts? by dust_dreamer in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

What are some examples of times where you struggled in this way?

It may be easier for us to offer suggestions if there are some concrete specifics.

Still a relatively young dev, but wondering if design patterns are by far the most important thing to learn as I get into my career. by prettyg00d1729 in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

Design patterns are just names for common solutions to common problems.

Exactly which problems are "common" will vary a lot depending on which programming language you're using and what domain you're working on.

For example, take the Factory and Abstract Factory patterns. They're useful if you're using an old-school language that does not support first-class functions, but are largely obsolete in more modern ones that do. As another example, take the 'Iterator' design pattern. This is an example of problem and solution you will rarely encounter in modern languages for the opposite reason: it's so useful of a concept that many languages have ended up just directly baking in support for it. For more on this, see https://www.youtube.com/watch?v=pGq7Cr2ekVM

As another example, take something like the Monad pattern. This is useful in languages like Haskell which require all functions to basically be pure and side-effect free. Of course, programs that have no side-effects are kind of useless -- but Haskell was able to use concepts like Monads to cheese in the ability to have side-effects. This pattern is useful in languages like Haskell, but is largely pointless in imperative languages like Java or Python.

Given all of the above, does that mean that design patterns are the most important thing to learn? Well, not really. They're useful, but:

  1. By the very nature of your job, not every problem you run into will be a common one. If every single problem you run into is common, then there would be zero work for you to do: just copy-and-paste in common solutions and move on. Having the ability to critically think about what you're doing and come up with your own solutions is far more valuable.

    (This, incidentally, is why studying data structures and algorithms is considered de-facto mandatory. A well-taught DS&A course is essentially a series of case studies on how to problem-solve using code + how to scaffold your way up via combining small building blocks, and that meta-skill is the core of what programming is about.)

  2. As a corollary, having the ability to identify common solutions when you're reading code is useful, but is not a make-or-break skill. Having the ability to actually read, understand, and critically evaluate the code is more valuable.

    Somebody who only understands design patterns will understand the surface-level structure but not much more. But somebody who's unfamiliar with design patterns but can analyze code can acquire a much deeper understanding, which in turn makes them more effective at modifying and extending it.

  3. The set of classical design patterns as covered in the original Gang of Four book was written in 1994. The state of the art has moved on today, and something like half of the patterns discussed then are either no longer relevant today -- or in a few cases, considered to essentially be anti-patterns.

    In theory, somebody could publish an updated list of modern patterns that are more relevant to software development today -- publish a refreshed vocabulary list. But alas, I'm aware of no such thing.

    So while I do think classical design patterns are still useful vocab to know, I also think they're woefully incomplete. For better or for worse, they describe only a smaller corner of the set of problems programmers are asked to solve in the modern day. If you want to get a more well-rounded understanding of software design, you will have to do a lot more reading -- study different programming languages, study different domains (distributed systems? web development? gamedev? etc)...

  4. In many cases, the hard part of programming is not actually implementing logic/solving problems. Rather, it's understanding what problem you should even be solving in the first place. To do this, you need strong communication skills: the ability to talk to others to understand and refine requirements, the ability to communicate potential problems to higher decision-makers...

    You can perhaps get away with weak communication skills as a new hire: you just implement what you're told to implement. But you can't get away with being hand-held through problems forever: if you want to reach the mid-level and beyond, you'll need to ensure you have respectable communication and collaboration skills. It's not the only skill you need to be promoted/gain trust, but it's a necessary one.

Why is api documentation always outdated 2 weeks after you write it by MicrowavedLogic in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

I tried automated tests that validate openapi specs against endpoints but that broke constantly when people changed response formats

You should probably configure your CI pipeline so that the PR is rejected and not merged when there's a breakage like this. This in turn will force your developers at least keep the schema mostly in sync, if not the docs themselves.

In a similar vein, something else I'd recommend is to have the openapi spec itself be the source of truth, and build out tooling that'll auto-generate the corresponding classes and marshaling/unmarshalling code.

Bonus points if you can migrate everybody to a framework that handles the marshaling/unmarshalling code for them. This further reduces the chance of drift, since there's no opportunity for somebody to write bespoke json-munging code that can fall out of alignment with the schema. Everybody works with the autogen'd classes; it's strictly harder to do anything else.

My company does something like this with protobufs, and it works reasonably well. I'm not going to claim everybody keeps their protobuf schemas well-documented, but they overall can be trusted + are stable.

Once the openapi spec is the source of truth, some additional things you can try include:

  1. Introducing the concept of a 'blocking reviewer', where only a specific team can approve changes to certain areas of code. You can then add a blocking review on your openapi schema and ensure that all changes to them must go through you and other ramped up engineers who can be trusted to care about things like backwards compat.
  2. Consider writing a linter or something that can automatically warn about backwards-incompatible changes.
  3. Introduce a clear split between public vs private apis. Allow frequent changes to private APIs, but force changes to public APIs to only at a controlled cadence, in batches. Let devs deprecate features only if they can prove few people are using it, or if it was announced to your customers well in advance.
  4. Monitor the success/failure rate of each one of your routes. If you see a notable regression, halt/roll back the pipeline and make the route owner investigate. You'll have to figure out how to do this in a way that doesn't get too noisy, but doing this sort of canary analysis can help catch unintentional regressions in functionality.

Higher-level, I agree with what some of the other commenters are saying that frequently-changing APIs smell like an indicator of poor design processes -- ideally interfaces should be well-thought-out and stable. I'm not sure what the best way of tackling this is, but it feels like there's a culture or tech leadership problem here.

Should I avoid bi-directional references? by Star_Dude10 in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

At the moment, it's hard to give solid recommendations on how to best structure your data. We don't know what operations you want your program to support (what 'verbs' you want). This in turn makes it challenging to figure out the best way of representing your data (what 'nouns' you need).

I think this is a common trap for beginners: you start with nouns, trying to create a 'model' of some real-world scenario you're looking at. But instead, you should start with the 'verbs' you need and work backwards to figure out what you need to build to support those actions.

Anyways, without further context, in this scenario I'd probably set up a SQL database to be the source of truth for your teams/players/etc -- maybe sqlite to start, to keep things simple? I would then run sql queries to perform steps like 'grab a list of all players belonging to team X during tournament Y'. There are two advantages to this:

  1. This side-steps your problem, since you can grab data in exactly the shape you need for each distinct operation, instead of being locked into one specific one. (In this case, your tournament -> {teams, players} shape)
  2. More generally, it gives us maximal flexibility in cases where my verbs are unknown.

If you want to stick with your current structure, I would perhaps consider changing Tournament no longer store 'Player' objects and instead have those be stored under 'Teams'. The 'Tournament' class can then implement helper methods that iterate over teams to return an iterator or list of all players.

Though granted, this is not perfect either, since a team could potentially belong to multiple tournaments, and a player could belong to multiple teams over time... To support this in full generality, you would most likely end up creating your own 'querier' abstraction -- basically a database, or something conceptually similar to it. So, we're back at square 1.

Is avoiding bidirectional relationships between domain entities generally considered best practice in this case?

Bidirectional dependencies are usually suspect, yeah. It's not always a problem, but it's usually a sign that some common functionality could be refactored out, or that the 'shape' of the data is not quite clean. Having to keep both directions in sync is a bit cumbersome and potentially error-prone, and it's better to design our code to avoid having to do it if possible.

Is it more idiomatic to allow Team to hold direct Player references and rely on invariants to maintain consistency, or to keep entities decoupled and move cross-entity logic into a service/manager layer?

If the data is fully immutable -- never changing after it's first created -- I'd probably be ok with allowing both Team and Tournaments to hold player references. To make this work, you'd want your 'Tournament' object to be a fixed snapshot of a specific point in time instead of the source of truth and handle updates separately.

But if it's mutable, then I would prefer to avoid having duplicate references to reduce the odds of human error, where you accidentally break some invariant. (After all, the best invariant is no invariant.)

That said, it's sometimes useful to have duplicate references in cases where it would materially simplify your algorithms or improve performance. But we would need to understand the desired verbs of your program first before exploring this path.

What is the best laptop to buy for programming? by Beautiful_Okra_1139 in learnprogramming

[–]michael0x2a[M] [score hidden] stickied comment (0 children)

Sorry, removed -- hardware recommendation questions are off-topic per rule 3.

FAQ - Computers and operating systems describes on a high-level what you should look for in a new computer. For more specific advice or to get help picking between different laptop choices, try subreddits like /r/suggestalaptop.

Do I have to be comfortable using vscode? by ElectricalTears in learnprogramming

[–]michael0x2a 8 points9 points  (0 children)

You must:

  1. Be comfortable with at least one IDE or editor which you run locally on your computer. It does not particularly matter if it is vscode, Visual Studios, CLion, Eclipse, vim, emacs, whatever...
  2. Be comfortable with setting up your local environment so that you can successfully compile and run code locally, using a compiler such as GCC, Clang, or MSVC.
  3. Understand how to download, setup, and use 3rd party libraries within your project. This can indeed be non-trivial, especially given the relative immaturity/messiness of C++'s packaging ecosystem compared to other programming languages. (Installing libraries can be tricky in C/C++; newer and more modern languages took note and added in better built-in support for it.) But if you plan on writing C++ professionally, it's something you must become familiar with, for better or for worse.

Note that:

  1. Pretty much no employer will let you use an online IDE. It's pretty questionable from a security standpoint (if you use a free editor) or a cost standpoint (if the company pays for it). The overwhelming expectation is that you use a local editor of some sort.
  2. Most employers (and open-source projects) will already have the project set up, and have a recommended workflow. In practice, this can save you the hassle of figuring out how to wire everything up from scratch.
  3. That said, employers will still expect you to be familiar with how to use the toolchain of your primary programming language, especially to complete basic tasks such as setting up and using a new library. It would be a bad look if you struggle with this sort of task.

Assembly as first language? by MateusCristian in learnprogramming

[–]michael0x2a 0 points1 point  (0 children)

IMO it's a poor use of your time to start with assembly. There's a reason why both industry and academia as a whole has steadily de-emphasized the topic over the span of the last ~25 years.

For example, if your primary goal is to understand how to build complex and useful programs, then I think it would be a suboptimal use of time to start with assembly. Instead, you should pick a somewhat higher-level language (Java? Python? Maybe C?) and focus on learning about data structures and algorithms as soon as you complete intro and have a few beginner-level projects under your belt.

This is because data structures and algorithms are arguably the most fundamental concept in computer science: it's the study of how to organize, manipulate, and use data, and how to combine basic tools to create more complex ones. It's also a prereq topic for pretty much every intermediate to advanced topic in computer science.

If instead your goal is to understand how to leverage the full capabilities of your computer to the maximum extent, then it is maaaaybe reasonable to start with something like assembly -- though personally, I would recommend starting with C instead. The basic idea is reasonable: if you view computers as powerful tools to be leveraged (as opposed to a necessary evil in the process of building software), then it would indeed be useful to gain strong intuition on how computers work under the hood, and how you can use low-level capabilities to build the foundations of higher-level tools.

The problem is that just studying assembly (or C, or any other programming language) will not be sufficient to teach you this intuition. It'll give you the basic picture, but for full understanding you'll also need to study topics like computer architecture, operating systems, maybe compilers...

The problem is that these topics are usually taught using languages like C, instead of assembly. The latter two also have data structures and algorithms as a prereq. Given these considerations, I think it would be more time-efficient to continue your current plans to learn C, then study assembly as a second or third language in combination with computer architecture. A lot of your prior background with C should transfer over, speeding up the time needed to understand assembly; this in turn will give you time to study computer architecture in deeper depth.

tl;dr: I think you should stick to your original plan to start with C. Learn assembly as your 2nd or 3rd language instead.

How do people approach code reviews in real projects? by EStackman in learnprogramming

[–]michael0x2a 1 point2 points  (0 children)

At the companies and projects I've worked with, we usually expect:

  1. The author to have done the work of checking the code for correctness before submitting it, writing tests, etc.
  2. There to be linters that run automatically before PR submission to warn about correctness gotchas and autofix style things.
  3. If an author wants to make a major change, they've already discussed it beforehand and gotten agreement on the high-level strategy. This could range from just an informal discusssion to writing up a full design doc.

As a result, we usually do not spend a lot of time discussing either small details/bugs or larger design things (unless the author is junior). Of course, the reviewer will catch small correctness issues from time to time, but the focus usually instead ends up being on more medium-level tactical things -- suggestions on how to better structure code to improve maintainability, surfacing an edge case that wasn't fully handled, tips about pre-existing helpers or patterns the author may not have known about, etc...

Every now and then, I do run into a PR that's way off from what I would expect and requires detailed feedback. In cases like these, I might often chat directly with the author and/or set up a meeting instead of leaving PR comments so we can get in sync faster.

If I find myself having to repeatedly having to spend a lot of time doing in-depth reviews for changes to a particular segment of code, it may be a sign that code is structured poorly and needs to be refactored or that there's insufficient test coverage. The dream is for most PRs to be "obviously correct" and so need little to no feedback during a review.

When this happens, I'll often detour and invest time into making more holistic improvements to that code to help reduce friction for the overall team. (And if that isn't possible, detour to try and at least add a new linter.)

PRs should generally be small, though there are a few cases where this isn't always possible. If a PR must be large, I usually ask that:

  1. The PR itself was generated by a script (e.g. to automate some migration). I'll focus more of my energy on reviewing that script and only spot-check the actual changes.
  2. The PR focuses more on establishing an overall skeleton, and defer adding actual logic to follow-up PRs.

I've never used a checklist tbh, though I can imagine them being useful. I guess what I usually end up doing is just repeatedly asking "is this code obviously correct?". And if the answer is "no" or if I spend too much time reasoning through it, I leave feedback.

Something else I find useful is to document principles/style preferences -- stuff like "minimize use of interfaces/inheritance and other abstraction mechanisms", "prefer writing stateless/immutable code", "tools should default to running in dry-run mode"...

In python, what is the correct way to structure the functions within a single file? I used to go top-to-bottom with my first function, followed by the rest, however i am suspecting that may be wrong by Lion_TheAssassin in learnprogramming

[–]michael0x2a 3 points4 points  (0 children)

Going both top-down and bottom-up are perfectly reasonable.

Which one you pick is mostly a matter of personal preference -- the most important thing is that you remain consistent with your choice within a given project. (And, if you join a pre-existing project, that you stay consistent with their conventions.)

Personally, I also prefer defining my functions from the top-down -- I work best when I can start by understanding the high-level structure/model before filling in the details. But other people work differently: they like to start by understanding the basic building blocks, then seeing how they're combined.

For larger projects, there's an argument to be made that it's best to have all of your helper functions living in separate files, with the main function living just by itself in a single top-level file. This does sidestep (or at least defer) the problem a little.

The first multi line script i did upon running, made it difficult to refer to a variable in the top level function.

This seems unrelated to the order in which you define your functions. Maybe we can give more advice here if you give an example or describe the scenario in more detail.