|
if you say post a comment to his answer he will (if he has them active in his profile) get a direct notification about your post. That's the most direct way to say "thanks" I know.
Doing it here is nice too, but could go unnoticed.
Summoning him as @OriginalGriff explained is a good method too.
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Erbsenzähler
|
|
|
|
|
You locked him in the root cellar?
|
|
|
|
|
And how is this message more useful than mine back then[^]?
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
I have an aversion to creating things like statically backed ersatz "singleton" classes in languages that support them.
I don't know why. I also hate using statics even when confined to the CPP implementation file. I think that is an artifact of me not starting out in C or C++ when I cut my teeth on code. The fact that CPPs are essentially separate and private to their associated header is still not completely instinct. I don't get that confused or anything, but my gut doesn't take it into account, I think.
I've been trying to clean up Somebody Else's Code - an old Nintendo emulator written in C that was designed to run on things like Pentium processors. It has endured because it's fast, decently cross platform, and it is good at emulation. It reads like the C language does - terribly.
I've been porting it to C++, and I initially did a dumb thing and started trying to make it non-static.
This was an unforced error - risible on my part in terms of design. There is absolutely no reason to run two instances of an NES emulator as part of a single program.
I did it because I am averse to making these statically backed "singletons", or really any statically backed code setup in a language that supports classes.
Gosh it's silly of me.
Real programmers use butterflies
|
|
|
|
|
From my perspective, most classes are simply containers to organize functions, rarely do they need to be instantiable unless one is dealing with a collection of things or the class is used in a thread and needs to maintain its own context. I think I'm biased because I've experienced a lot of poorly designed OO progs.
|
|
|
|
|
Way back in college I learned that "There are Liars, Damned Liars, and in a class by themselves, Statisticians". Perhaps this is the reason.
In my opinion, statistics are way to "fuzzy". You can say/prove anything you want to with them.
You are using languages that are way beyond me. I am a humble VB programmer, VB6 for legacy apps, and VB.Net for new development.
ed
|
|
|
|
|
Before I was proficient at C++ and prior to .NET I was using a ton of VB6. I spent a lot of time hacking it to get it to render professional and snazzy interfaces.
This site helped with that a ton: Visual Basic Accelerator Home[^]
Real programmers use butterflies
|
|
|
|
|
So,
What other languages do you use? Do you do javascript or web stuff?
|
|
|
|
|
I really don't like web development to the point where I've deliberately let my JS and HTML skills rust so I could honestly say I'm not the developer you want for that.
Frankly, I use what I need to. I even learned a bit of python in order to port some old Win3.1 .FON file loading code from it.
Because of that, I've used Java, C, C++, C#, VB, VB.NET, ASM (various platforms), 6502 bytecode (before i discovered assembly), Python, JS (way back when), Pascal, and probably other languages that aren't occurring to me right now.
Real programmers use butterflies
|
|
|
|
|
Hmmm,
Are you proficient with WinDbg, IDA Pro and/or Ghidra?
|
|
|
|
|
WinDBG I used to be, but I haven't used it in forever.
Real programmers use butterflies
|
|
|
|
|
"Use the right tool for the right job." -- Scotty et al
I write a lot of library routines, so statics are the norm.
I am also not a fan of singletons as they make no sense from a design viewpoint.
I have yet to see a convincing argument in favor of singletons for anything mission critical.
BUT! As it turns out, I wrote a family of five (!) singletons yesterday. Each implements a MAC address parser with a different level of leniency -- from Strict to Wild West.
This is still essentially a set of library routines, but each is implemented by a different specialized singleton, accessible only via one static class. (I didn't bother with making them lazy; all they contain is a Regular Expression.)
It's sort of like the family of System.StringComparer s or System.Text.Encoding s.
P.S. -- C# of course.
modified 11-Dec-21 11:45am.
|
|
|
|
|
You can't create static "user controls" or windows; they have to be instantiated; and if you only want / need one, you wind up with a singleton. For that matter, an app can be a singleton (via Mutex) if no 2 instances should be run at the same time due to file contention, etc.
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
|
|
|
|
|
And I hate statistics much more over statics
|
|
|
|
|
I hate Singletons because they are awkward as hell to use. Usually, if you only need something to be instantiated once, just instantiate it once! The only reason I can see to use a Singleton is if you are working with a lot of people on a codebase, and some of them may not have the capacity to follow simple rules like 'only create it once.' On the other hand, I love statics for functions that set themselves up on the first run. For instance,
void Something::something() {
static bool initialized = false;
if (!initialized) {
doSomething();
initialized = true;
}
} This has came in handy a few times.
|
|
|
|
|
Unfortunately, I can't afford the overhead, particularly since many of my functions are purely called with registers rather than creating additional stack frame. If I add a this pointer, that all falls apart and my frame rate suffers.
Real programmers use butterflies
|
|
|
|
|
Do you use a lot of static objects and functions, then, or have you solved those problems entirely through template metaprogramming?
When I discovered that I could make almost C-like code but still use classes in that manner to get the organizational benefits, I was pretty impressed by the flexibility of C++.
|
|
|
|
|
Statics for this. Templates don't make a lot of sense for the emulator. They do for the video driver I was working on but that is a different ball of wax
Real programmers use butterflies
|
|
|
|
|
'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
|
|
|
|