|
'Xactly.
The idea of "we need only one, therefore we must enforce only one" is wrong in nearly all situations -- it is not a problem to be solved.
If a team contains untrainable members, then the appropriate solution is to remove those members from the team.
|
|
|
|
|
I use singletons[^] freely even though I follow OO principles unless not doing so makes the code far clearer. For example, I'll define a virtual function that returns an object's type if this enables some pragmatic switch statements whose case clauses would be unwieldy if actually implemented in virtual functions of their own.
In C, a static is often a global, with the free-for-all that too easily ensues. In C++, a singleton can encapsulate its data and only modify it through functions that serve specific purposes. The same thing is possible in C if the functions are in the .h and the static is buried in the .cpp, but that's not what comes naturally to most C developers.
|
|
|
|
|
I have to be very careful with this code. Anything I do to de-staticize it can potentially impact performance severely, and also complicate it since it uses a lot of function pointers that it passes around. I'd have to add state parameters to get back to the class instance if it wasn't backed statically.
So what I'm doing is like this:
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "nes_core.hpp"
namespace nes {
struct apu_context;
struct apu_ext;
enum struct apu_filter_type
{
none,
low_pass,
weighted
};
class apu final {
static void initialize(double base_freq, int sample_rate, int refresh_rate, int sample_bits);
static void deinitialize();
static void set(double base_freq, int sample_rate, int refresh_rate, int sample_bits);
static void process(void *buffer, int num_samples);
static void reset();
static void ext(apu_context *ctx, apu_ext *ext);
static void filter(apu_filter_type type);
static void channel(int chan, bool enabled);
static uint8_t read(uint32_t address);
static void write(uint32_t address, uint8_t value);
static apu_context* context();
static void context(apu_context* value);
};
class apu_context {
protected:
inline apu_context() {}
};
class apu_ext {
protected:
inline apu_ext() {}
};
}
And then in my CPP I have:
#include "nes_platform.h"
#include <nes_apu.hpp>
#include "nes_apu_defines.h"
#include "nes_reader_writer.h"
#include "nes_apu_context.h"
namespace nes
{
enum
{
APU_FILTER_NONE,
APU_FILTER_LOWPASS,
APU_FILTER_WEIGHTED
};
void apu::initialize(double base_freq, int sample_rate, int refresh_rate, int sample_bits) {
...
All of those .h files are "private" includes that don't exist under the "/include" folder but the "/src" folder since they are actually part of the implementation.
That way:
- I can keep most of the implementation static for performance and to simplify callbacks
- I can keep 75% of the structure of the existing C code.
- I hide all the nasty in the CPP and H files away from the user's namespace
- I can very easily wrap it later with a real singleton class if i want
Real programmers use butterflies
|
|
|
|
|
When I only have one of something that I need to share across a multi-project app, I use a "global static" (class). Trying to maintain references, parameters and avoiding cycles otherwise is (for me) extra time spent for nothing.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
I know it's pedantic, but the right tool for the job. I'll grant you that the singleton pattern can be overused, especially by programmers who aren't proficient at OOP principles like encapsulation and data hiding. "But I need this value over here too, and I don't know how to make that happen unless I let everybody see it." Globals, globals everywhere.
The most common use I make of static ly-declared 'singleton' values is where there is one instance of a thing but multiple users. In this case, the users are implemented as instances of the class around the static value. The instances then mediate access to the static value by the class user.
I know what I'm doing... I'm a professional.
Software Zen: delete this;
|
|
|
|
|
I built this so I can easily layer that very thing on top of what I have but I don't think it will be necessary.
Real programmers use butterflies
|
|
|
|
|
That makes sense though.
There is a time and a place for singletons. I'm not denying that. I just don't like them. They "smell" to me.
They do solve some very sticky design problems though, particularly when you're creating binary interfaces to be used across DLL/EXE/NETWORK and you need a "factory" to create objects from. That's probably where I've used them the most, because you can't export static "interfaces" with binary interface binding like that. (Think COM or DCOM, or really any kind of binary RPC)
Real programmers use butterflies
|
|
|
|
|
I don't like singleton.. but I have nothing against static method (aka functions)..
So I am halfway there!
|
|
|
|
|
So you and I are on the same page there.
Real programmers use butterflies
|
|
|
|
|
Nice!
I had a brainwave. I suspect the popularity of singleton classes goes hand in hand with unit testing with mocks. Another thing I dislike, though I would sometimes concede them the title of necessary evil.
Anyway, you can't swap a static class since the code is directly accessed by consumer. But if the class is passed as a constructor argument to consumer, then you can swap it for something else there...
|
|
|
|
|
Super Lloyd wrote: hand in hand with unit testing with mocks. Another thing I dislike, though I would sometimes concede them the title of necessary evil.
Yet another opinion we share. I don't do unit testing unless I have to. For my non-commercial code, I don't really write that much in the way of tests until I have to. I know that's evil of me, but there it is. I figure I'm just challenging myself to write more stable code the first time. Yeah, that's it. *whistles*
I can wrap the static methods with a class that just delegates to them, which is what I was referring to when I said "ersatz 'singleton'" - I just don't like it. I prefer the statics, but even that I don't like.
Real programmers use butterflies
|
|
|
|
|
honey the codewitch wrote: I have an aversion to creating things like statically backed ersatz "singleton" classes in languages that support them.
One of my previous managers was talking: I send programmer to C++ design course, after such course he writes only singletons.
Yep, for C++ programmer, the simplest way to look smart is to write a singleton.
|
|
|
|
|
"If you learn nothing else, learn singleton" -- and they learn nothing else.
|
|
|
|
|
I'm forced to write either a static class (like what I have now) or an ersatz singleton backed by that static class (wrapping it)
I'm sticking with the all static class.
I can't afford the this pointer to create a real singleton for the kind of things I'm doing. Right now all the arguments to calls are being put in registers, but I only have so many of those, and this is all critical code paths - anything I do impacts the final framerate of the emulator.
I have to be very careful in my design here. I can't get fluffy. I can't afford it.
Real programmers use butterflies
|
|
|
|
|
Here they are translated to English, using a flip chart: Bec Hill translates "Non Je Ne Regrette Rien" (Edith Piaf) - YouTube[^]
May be slightly NSFW depending on your Internet Police, so watch at home if you are not sure.
Made me laugh anyway!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
She must be the daughter of Benny Hill!
|
|
|
|
|
Not really, being French meself!
|
|
|
|
|
Q. What do you call someone who speaks three languages?
A. Trilingual
Q. What do you call someone who speaks two languages?
A. Bilingual
Q. What do you call someone who speaks one language?
A. English
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
There is a woman who hangs around the play-ground offering cheap batteries.
She sells 'C' cells by the seesaw.
The less you need, the more you have.
Even a blind squirrel gets a nut...occasionally.
JaxCoder.com
|
|
|
|
|
You're fired! Here's your coat.
|
|
|
|
|
Please explain the joke.
I do a bit o' English, but this beyond me. And it's a spade, not a shovel.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
It is an English "tongue twister", i.e. a phrase that gets difficult to say multiple times, especially at speed. Ofte used as a children's game. The original phrase is "She sells sea-shells by the sea shore".
|
|
|
|
|
Thanks. And good exercise.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Good point ... I know about "she sells..." from my English lessons some time ago, and now I also know the meaning of "seesaw". And... both tongue-twisters can even be combined in one sentence ...
|
|
|
|
|
No, Bob.
Just sign the divorce papers and you can both move on with your lives.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|