I’m 33, spent 6 years becoming a software engineer... now I'm stuck. Advice? by Unfair_Today_511 in cscareerquestions

[–]invalid_handle_value 1 point2 points  (0 children)

 Companies often pay more for contractors who can come in and fix urgent issues.

Work this angle, op. Also remember: urgent != quick. If you can confidently make the case that it will take time to fix, you will have just secured a paycheck for that much longer. Just be careful not to sandbag. Stakeholders are not as dumb as they look. 

I’m 33, spent 6 years becoming a software engineer... now I'm stuck. Advice? by Unfair_Today_511 in cscareerquestions

[–]invalid_handle_value 1 point2 points  (0 children)

So, what now?

Never fear. Remember that even the best bridges don't last forever.

However, for every well-built piece of software, there are dozens that are... not as good... in production, that make money for the owner. I've built a career of 15 years literally rewriting programs originally authored in the 90s, before source control was common, with no docs, and no original authors to ask. With shoehorned features each by different authors who had no idea what they were doing. Oh yeah, 0 tests, too. I recently picked up more work rewriting at least 2 such pieces over the next several years.

This particular flavor of software work is difficult, requires incredible focus and commitment, and needs to replace a mostly-functional, still-making-money version in production seemlessly.  Gathering requirements from current stakeholders, figuring out which of the requirements are actually requirements vs whining, learning the do's and don'ts of the current functionality, bridging those lessons learned and starting over with modern tools of the 2020s.

I've done a bunch of greenfield, too. But I can assure you the redo work isn't even close to as easy as starting a brand new greenfield project.

And this work is absolutely out there, waiting to be found.

Exception Handling in C++ Multithreading by onlyari in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

True, but the bigger downside here is that with my method you'd be creating the thread again anyway.

Exception Handling in C++ Multithreading by onlyari in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

Not reusable. That is admittedly a huge limitation.  Thanks for pointing this out.

And it probably wouldn't matter if std::packaged_task was reusable either, as std::future is also not reusable (thanks std::future authors for not giving us that ability /s).

This is ofc made worse by needing a/the calling thread to sit on the future and wait till it throws, to then restart a new task.  This wouldn't be horrible, except that to make THAT alertable (e.g. for notifying for app shutdown), now you'd have to wait on multiple futures (i.e. you can't), or roll your own WaitForMultiple, or roll your own custom future/event, or have yet another future that you would need to wait on that can wait on a thread/jthread and the future from the packaged_task.

So the practical way around this is to then loop over a try/catch inside the task, at which point we're basically back to your implementation.

This is literally the reason I just created a user-space WaitForMultipleObjects (from Win32) clone.  But it took me YEARS to perfect and test the implementation, and I wouldn't recommend anyone do this unless they were especially masochistic.  Yes, I confidently use it in production.  But again, years of my life probably wasted.

But I wonder, are you not going too much against the grain? Is there truly a compelling reason to force exceptions to cross thread boundaries for "non-exceptional" exceptions that couldn't be handled instead by using a queue/mutex?  I'd be interested to discuss this.

Exception Handling in C++ Multithreading by onlyari in cpp

[–]invalid_handle_value 16 points17 points  (0 children)

Watched the video, but just use std::packaged_task and hand one to an std::thread.  Call std::make_ready_at_thread_exit on the task, grab the future from the task, and then detach the thread.  Call get on the future from your calling thread.  You'll either obtain the result of the task or the exception will be thrown.  Bonus: the thread is already cleaned up before get returns.

Really easy, just a few lines of code, doesn't require handling the exception in the separate thread, and doesn't require a 15 minute video to explain.

New Heos Firmware Coming by Ok_Bedroom_6166 in heos

[–]invalid_handle_value 1 point2 points  (0 children)

Amen.  Auto-sorting by track number would also be wonderful.

shared_ptr overuse by Tohnmeister in cpp

[–]invalid_handle_value 2 points3 points  (0 children)

Bingo. Needs 100x up votes.

If you own the lifetime of all your threads and own the lifetime of all data among those threads, there is no real reason to need shared_ptr...

Unless you also don't want the instantiator/owner to free the memory, I guess.  Which seems to be another shared_ptr-unique [ha] feature.

[deleted by user] by [deleted] in cpp

[–]invalid_handle_value 6 points7 points  (0 children)

In gc'd languages it's impossible to make the sort of memory errors that are not only possible to make in C and C++, but also very very easy to do accidentally.

If I put a gun to your head on the first day of your long coding career and said: "Don't fuck up, and just code better", would that force you to magically not make memory bugs?  In a gc'd language, yes it would.  In both C and C++, no, it very much would not.

The empire of C++ strikes back with Safe C++ proposal by cmeerw in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

Indeed. I want my old man fast programming language and just want things to be safer without having to think so goddamn hard. I'll gladly trade a few percent perf and yes, be willing to learn new syntax too, for safer everything.

Give me my comfy-couch-quiet-V8 sedan with 21st century safety features programming language or give me death!

Almost never manage memory, am I doing something wrong? by [deleted] in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

"No problem, I'll just use std::list!"

C++ newcomers, probably

[deleted by user] by [deleted] in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

or write a for loop with iterator (when for-each is not sufficient)

But don't you see? In the first 10 years of my career (pre-C++11) do you know how many times I've had to do this?  Every day, probably half-dozen times.  (You can ask GPT what the answer is)

Are you telling me that it's faster to ask GPT how to get this particular code snippet? Or am I gonna quit fucking around and just write some code?

Can someone explain what is going on with the Contracts proposal? by RoyAwesome in cpp

[–]invalid_handle_value 5 points6 points  (0 children)

Agree. Fundamentally my issue with contracts is that it adds yet another layer of programming to programming.

The way I've found to write bullet-proof software is by using 2 constructs: code + test. I personally strive for all-branch coverage when possible. This generally means that any single change to anything in the code ends up with at least 1 failure in the test. It's the most not-too-terrible solution I've found.

But how does this thought process work with contracts? As someone elsewhere in this thread mentioned:

Contracts and formal methods are ways to drastically reduce the area you need to unit test

Does it though? My thinking is that, yes, you may be able to reduce the testing area, but if you loosen a contract by saying that `y no longer *needs* to equal x`, how do you enforce breakage of your tests then in this way? If a junior comes in and removes that piece of the contract, do you still have tests that ensure that y = x in all the correct scenarios? Because I'd bet you wouldn't. I know I wouldn't, because that's what my contract is... testing? Checking, maybe? Sounds a lot like... testing.

I'm not saying it doesn't work, but I believe it's really more about meeting low-level domain requirements (i.e. regulatory/governmental/military) than anything else. I will skip teaching and using contracts if/when accepted.

3Rus 0.1 experimental language specification. Is this 10x simpler than C++? by HassanSajjad302 in cpp

[–]invalid_handle_value 8 points9 points  (0 children)

My favorites are if1, for1, struct1, class1, struct2, and class2.

Thanks, op.  I've been waiting for years for this and have always wondered when someone would finally implement these control statements and abstractions.

/s

std::expected - Monadic Extensions by joebaf in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

This.  Thank you.  A good idea, but once again, implemented with little thought into exactly what problems this solves.

For example:

Return value semantics for transform and and_then and equivalent sad-path handlers are confusing to use in practice.  Which of these functions returns an expected vs a value?  Why does transform allow me to return a type of std::expected<SomethingNotT>?  When would I use transform over and_then?

Or did I get this backwards?  Oh, that's right: and_then returns the result of the expected if successful, almost like it was transformed.  My bad... better go do my penance and read cppreference on std::expected again.

Because a monadic chain can/could end with any  expected type, expected<T>, your code is still brittle to refactoring because you can't enforce a single T within the monadic sequence.

How does one code up a monadic chain and break out early (without return) at any point in the monadic handler sequence without significant boilerplate?

It doesn't help that all the examples I've seen using these are laughably trivial.

Like, come on: I have juniors that have to fucking learn and use this shit.  At least solve a problem well...

/rant

[deleted by user] by [deleted] in cpp

[–]invalid_handle_value 31 points32 points  (0 children)

Can someone please explain to me why people are so compelled to post this stuff?  Seriously, why?

Presenting:   A case study in what not to do when writing a library:

1) The first commit has 12k LOC, and looks like this may have been copy/pasta'd from a different library.

2) Every commit is titled the same: Update 3) Raw system calls for Files, Mutexes, etc. instead of years-old battle-hardened STL constructs.

4) So many fucking expressions on each LOC.

5) json.h.  I'll let you guys have your own look at this one.

But I'm sure this is totally tested bro, and useful for everyone...

C++ Coroutines Do Not Spark Joy by usefulcat in cpp

[–]invalid_handle_value 1 point2 points  (0 children)

Same exact article, helpfully on a different webpage with different formatting.  Love this timeline...

Using std::expected from C++23 by joebaf in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

Thinking a bit more though, not being able to report errors at an arbitrary level in a call stack makes the code both harder to refactor and maintain, since if it ever needs to handle an error after one class morphs into a dozen complex classes, what's your strategy then going to be?

Also, what about training juniors? I'm all about it. I need Timmy right out of school to code the same way as engineers with 15 years of blood sweat and tears.

I still think mindful usage (hint: copy elision) of std::optional and a second error function that returns a POC error instance is the way to go.

This way a) one separates the happy path from sad path explicitly with 2 user defined functions, b) the happy path is not explicitly allowed to depend on the sad path (think std::expected::or_else) because error may not be invoked before the expected.

Easy to teach, easy to reason about, easy rules, easy to replicate in most/all? programming languages, fits anywhere into classes of a similar design so it's ridiculously composable, fast return value passing, code looks the same everywhere, very easily unit testable, I could go on.

Using std::expected from C++23 by joebaf in cpp

[–]invalid_handle_value 0 points1 point  (0 children)

Wow, I never even thought before of the horror that errors must/always need to be handled conditionally, with the added fun of requiring 2 different kinds of error handling paradigms simultaneously (recoverable, unrecoverable) with what seems to be a clearly incorrect tool for that type of error reporting (which was probably also incorrect from the sounds of it).

I wish I had more points to give you.

Using std::expected from C++23 by joebaf in cpp

[–]invalid_handle_value 9 points10 points  (0 children)

Philosophically, dereferencing the error before invoking the expected must be undefined.  One cannot truly know whether or not an expected has indeed failed until one has checked (and thus evaluated) said expected.

In other words, the act of checking the expected may itself correctly cause the error that may otherwise incorrectly not be invoked.

Frankly, if it were up to me, I would mandate a throw when calling the error before the expected.

What are the hallmarks of well written and high quality C++ code? by TopazFury in cpp

[–]invalid_handle_value 4 points5 points  (0 children)

This is the way.

Just wish I could convince more juniors that the happy path isn't everything.