Being the only person able to program in a small team, I know I am the target of the criticism in this post.
I think it is mostly true, I wish there were other people looking at my code, but for years I've been working on projects alone.
What I came to realize is that there are some kinds of software where quality is paramount, mainly the code that will carry on for years, and require constant changes.
But there are some software that only exist to fix a particular issue that doesn't require change over time. The typical Perl script that lives unchanged for years doing a single task. For this particular case, quality matters less than portability and relying on solid dependencies that do not require maintenance.
In the end, management does not care about code quality, as long as money is flowing.
For lonely programmers, identifying the code that should be high quality (the one you will be looking at continuously) and the one is only there to fix a single problem is really important.
> For lonely programmers, identifying the code that should be high quality (the one you will be looking at continuously) and the one is only there to fix a single problem is really important.
I feel your pain. I am the main coder, in a small team. There's one server guy (part time), and one semi-technical graphic designer (also part time), a couple of admin/marketing folks (also part time), and me (full, full time).
My software is really good, and I don't need anyone else to tell me it is or isn't.
That said, I am also quite aware that I have to make compromises, and that there are things that I'm not good at.
For example, I'm a higly advanced Swift programmer. I write Swift, every day (like, seven days a week, 52.14 weeks a year). I'm good with UIKit, and reasonably good with the other frameworks.
Server-side, I've been writing PHP for over 20 years, and never really got full mastery of it. I can write some very performant and robust server infrastructure (a lot of it lasts a long time, too), but I don't pretend that some kid couldn't code me into a corner.
But they might have trouble doing that, with Swift.
Doesn't stop them from being real judgmental, though. I suffered from that, myself.
Here's an example of stuff I do, now, that I would have sneered at, just a few years ago[0]:
let distance: CLLocationDistance = CLLocationDistance(rawMeetingObject["distance"] as? Double ?? Double.greatestFiniteMagnitude)
That uses a nil coalescing operator (??). In some cases, I can go through several of them, on one line (cascading nil coalescing operators).
That says that I need to get something from the "distance" key of a parsed JSON Dictionary, and, if it is not available (either as a key, or as a value that cannot be coerced into a Double), then I should return the maximum Double value (so it will blow up the distance sorters).
Here's a slightly more involved example (from a proprietary app):
If there's no default value in either the runtime, or the app defaults, then I use the hardcoded default. The reset is always false, after the first run.
That's actually fairly typical advanced Swift. I used to rail against it, but now, I do it all the time. I also tend to use tail closures a lot (that's when you declare a closure at the end of a function parameter list, so you can simply open the closure as a function result). That's also something I used to rail against.
If someone wants to maintain my code, then they need to have some decent chops. Usually, that's me. I will often revisit code that I wrote, six months ago (or more), and have learned how to read it. I write code that I want to see again; not some junior programmer.
Usage of the nil coalescing operator is not advanced. You've simply used it in a way that makes it less comprehendible to anyone not already familiar with the operator. Any actual Swift developer should be able to understand what's happening. But frankly, this isn't good code, and not just because you're using coalescing like that.
1. You should never have to use a raw object like that. Use a Decodable type and get a real Double from the parser. Among other things you have no error handling here to tell you when that as? Double cast fails. First thing you do in Swift is embrace the type system.
2. Fallbacks like that probably shouldn't be done inline. Instead, there's usually a facade on top of things like UserDefaults to properly name and handle different properties consistently. Using rawValue that much should be an obvious smell.
3. Use of untyped Any is almost always a bad idea in Swift. Create a proper type that encapsulates exactly what you should see and you'll likely write less code with fewer bugs.
4. A CLLocationDistance created from .greatestFiniteMagnitude is obviously an invalid value, so I assume you're checking it further down the line to see that. Better to just produce an error or a nil value when you don't have an actual distance than to pollute your system with invalid data.
Cool. If I'm doing it wrong, I wouldn't mind seeing it done right. I'm always willing to learn new stuff, and one thing that I've learned about Swift, is that there's always more/better ways to do stuff.
The obvious issue with not using rawValue, is that we don't use an enum, and that's what I usually see. I like to use enums, where others use static lets, because I can do things with enums, like limit the number of values (good for switches), and repurpose them, from time to time.
Also, since an enum is a type, I can add things like functions to do cool stuff, like extract and interpret the state, or do some good debug stringing. I could also use a struct, but why, if the enum will do it?
And, of course, since it's a type, I can extend it for special applications. I do that, a lot.
One of my "desmeller" exercises, is to go through my code, looking for "magic number constants," and see if I can replace them with enums.
The reason for the Any, is because the code extends another SPM module that I wrote, that forms an infrastructure for preferences, and this is just the bit inside the implementation.
No, the highest Double isn't an invalid value (that's actually the point). It's just one that won't apply to the filtered set that I produce, later on. That means I don't have to put in special branches (keeps the CC low), to look for invalid values.
I could also clamp it, but that can have unfortunate side effects, and I can add some assertions in the else clause.
Sometimes, there may be reasons for people doing stuff, other than they suck. I don't suck. I'm not being snooty, but I do this a lot, and have a lot of pretty good stuff, out there.
Maybe, and I know this is just crazy talk, I might actually be a halfway decent programmer.
I think it is mostly true, I wish there were other people looking at my code, but for years I've been working on projects alone.
What I came to realize is that there are some kinds of software where quality is paramount, mainly the code that will carry on for years, and require constant changes.
But there are some software that only exist to fix a particular issue that doesn't require change over time. The typical Perl script that lives unchanged for years doing a single task. For this particular case, quality matters less than portability and relying on solid dependencies that do not require maintenance.
In the end, management does not care about code quality, as long as money is flowing.
For lonely programmers, identifying the code that should be high quality (the one you will be looking at continuously) and the one is only there to fix a single problem is really important.