|
|
Shouldn't that be:
var a='matter', b='matter', c='matter';
|
|
|
|
|
Perfect!
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
Globals are a tool. Sometimes that tool comes in handy. I like globals a lot more than I like Singletons, especially if globals are wrapped in a class so they aren't scattered everywhere. Singletons, on the other hand, gnnhhhh!
(I've never felt that the verbiage to use Singletons was any better than just making sure you only implement a class once in the codebase. But if I found a place where a Singleton absolutely made sense, I'd use a Singleton.)
|
|
|
|
|
David O'Neil wrote: But if I found a place where a Singleton absolutely made sense, I'd use a Singleton I use it to keep a single instance of a logger that is used all over the application. The logger uses a blocking collection and so all other places can send stuff to the logger, the collection takes care of the entries and the logger just writes down in FIFO mode.
Would that be something making sense to you? (Just curious, I am not saying is absolutely making sense or correct, but I found the approach not that bad)
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.
|
|
|
|
|
Viewing it from your perspective, it makes sense. Personally, I'd just create one instance of the logger in a global and use that everywhere. I know there is only one global, and everything in that global only has one instantiation, so I never worry about it beyond that point. I'd just make certain to place the logger at the top of the declarations in the global, so it can be used by any of the following items.
The reason I settled on the global approach is linked to my Pimple article. It just makes things easier for me. It might not make your workflows easier. I don't know, and I'm not going to be all evangelical about my methods. If it works, it works. The goal is software the user can use. Not to avoid singletons or gotos or globals.
For instance, here's the current global header for my main MIDI project at this point:
#pragma once
class Globals {
private:
uchar lastNoteVelC;
MUSIC_TIME lastNoteLenC;
MUSIC_TIME snapValueC;
public:
Globals();
~Globals();
void saveAppDefaults();
enum NoteDurations { wholeNote=3072, halfNote=1536, quarterNote=768, eigthNote=384,
sixteenthNote=192, thirtySecondNote=96, sixtyFourthNote=48, tick=1 }
noteButtonDurationC;
int noteButtonDuration() { return noteButtonDurationC; }
uchar lastNoteVel() { return lastNoteVelC; }
void lastNoteVel(uchar vel) { lastNoteVelC = vel; }
MUSIC_TIME lastNoteLen() { return lastNoteLenC; }
void lastNoteLen(MUSIC_TIME newLen) { lastNoteLenC = newLen; }
MUSIC_TIME snapValue() { return snapValueC; }
void snapValue(MUSIC_TIME val) { snapValueC = val; }
private:
std::unique_ptr<app::ControllerNames> controllersC;
public:
app::ControllerNames & controllerNames() { return *controllersC.get(); }
private:
std::unique_ptr<app::NoteValMap> noteValMapC;
public:
app::NoteValMap & noteValMap() { return *noteValMapC.get(); }
private:
std::unique_ptr<midi::KeySignatures> keySignaturesC;
public:
midi::KeySignatures & keySignatures() { return *keySignaturesC.get(); }
private:
bool useSyncLogicC;
public:
void useSyncLogic(bool state) { useSyncLogicC = state; }
inline bool useSyncLogic() { return useSyncLogicC; }
private:
bool playPriorEventsC;
public:
bool playPriorEvents() { return playPriorEventsC; }
void playPriorEvents(bool state) { playPriorEventsC = state; }
private:
double ticksPerPixelC;
int keyHeightC;
public:
inline double ticksPerPixel() { return ticksPerPixelC; }
inline void ticksPerPixel(double val) { ticksPerPixelC = val; }
int keyHeight() { return keyHeightC; }
void keyHeight(int height) { keyHeightC = height; }
public:
enum DisplayVal { DisplayTicks, DisplayTimes };
private:
DisplayVal displayValC;
public:
DisplayVal displayVal() { return displayValC; }
void displayVal(DisplayVal val) { displayValC = val; }
private:
int stopSleepTimeC;
public:
int stopSleepTime() { return stopSleepTimeC; }
private:
bool showHelpOnStartupC;
public:
bool showHelpOnStartup() { return showHelpOnStartupC; }
void showHelpOnStartup(bool state) { showHelpOnStartupC = state; }
public:
enum StopMethod { PlayNotesOff, PlayOmniModeOff, PlayOmniModeOn, PlayMonoModeOn,
PlayPolyModeOn, PlayNothing };
private:
StopMethod stopMethodC;
public:
StopMethod stopMethod() { return stopMethodC; }
void stopMethod(StopMethod newMethod) { stopMethodC = newMethod; }
private:
int pianoViewBottomNoteC;
public:
int pianoViewBottomNote() { return pianoViewBottomNoteC; }
void pianoViewBottomNote(int x) { pianoViewBottomNoteC = x; }
private:
std::unique_ptr<ui::UIManager> uiManagerC;
public:
ui::UIManager & uiMan() { return *uiManagerC.get(); }
private:
std::unique_ptr<medit::Strings> stringsC;
public:
medit::Strings & strings() { return *stringsC.get(); }
public:
wString appWorkDir();
private:
int buttonHeightC = 25;
public:
int buttonHeight() { return buttonHeightC; }
private:
std::unique_ptr<utils::DateVersioner> dateVersionerC;
public:
utils::DateVersioner * dateVersioner() { return dateVersionerC.get(); }
public:
bool breakPointTrigger;
private:
int minTicksBetweenCurveEventsC;
public:
int minTicksBetweenCurveEvents() { return minTicksBetweenCurveEventsC; }
};
It is simple, and I control the instantiation order of everything in it. Some of it is rarely used in the rest of the codebase, but the UIManager it extensively accessed from almost everywhere for all the color choices and everything else related to UI. Knowing that things are there, my life as a programmer is easier.
As per gotos, I only have a few in my work. Here's one location that seems to be a good choice, from my perspective. It is the way my brain thinks of the solution. I know they could be eliminated, but I believe it would take several more lines of code to do so, and I have better things to worry about than whether the code is 'goto'-free:
void Repeat::createRepeatedMsgs() {
if (!createdMsgsC.empty()) throw dwl::Exception(_T("Delete created msgs prior to "
"creation"));
app::MsgPlayMap & holder = trackC.playMap();
holder.setPtrPos(s_cast<MUSIC_TIME>(0));
midi::BaseMsg * msg;
midi::BaseMsg * msgToCopy;
while ((msg = holder.msgAtPtr()) && msg != nullptr && msg->tick() < endTickC) {
if (msg->tick() < tickC) goto breakout;
for (size_t i=1, count=numRepeatsC; i<=count; ++i) {
midi::BaseMsg::Type type = msg->type();
if (type == midi::BaseMsg::Type::NoteOn) {
midi::NoteOn * noteOn = s_cast<midi::NoteOn *>(msg);
midi::Note * note = s_cast<midi::Note*>(noteOn->parent());
if (note) msgToCopy = note;
else msgToCopy = noteOn;
}
else if (type == midi::BaseMsg::Type::NoteOff) goto breakout;
else if (type == midi::BaseMsg::Type::KeyAftertouch) goto breakout;
else msgToCopy = msg;
if (msgToCopy->copyOf()) goto breakout;
std::unique_ptr<midi::BaseMsg> newMsg = msgToCopy->copyToTick(msgToCopy->tick() +
durationC * i);
if (newMsg->type() == midi::BaseMsg::Type::Note) {
s_cast<midi::Note*>(newMsg.get())->noteOn().copyOf((midi::BaseMsg*)1);
s_cast<midi::Note*>(newMsg.get())->noteOff().copyOf((midi::BaseMsg*)1);
}
createdMsgsC.push_back(newMsg.get());
newMsg.release(); }
breakout:
holder.incMsgPtr();
}
for (auto msg: createdMsgsC) {
msg->addToVisible();
}
}
|
|
|
|
|
I like singletons. I don't force it on the programmer though. My apps usually singletons for the DAL, connection string, and app configuration settings, and in my objects that use the singletons, I add properties that ease the typing you need to do to access the singleton objects. I also have a static Globals object.
Arguments against either singletons and globals are pointless, because a decent programmer knows when and how to use either one.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
#realJSOP wrote: app configuration settings
#realJSOP wrote: I also have a static Globals object
These really make sense and are actually thought out. The real issue with globals is that newer devs may create single global variables all over the place and then you just have this pile of stuff that cannot be managed. That's the real problem I'm talking about. And namespace crashes -- oops someone used that var name somewhere else and I didn't know it and now I've just clobbered their value and they've clobbered mine.
|
|
|
|
|
My reply is encapsulated in my reply to Nelek, up above. In short, if it works for you, it works. That's all that matters.
|
|
|
|
|
I use singletons freely, especially as flyweights[^]. But there are also other uses, such as threads that each perform a specific function.
|
|
|
|
|
Wow, flyweight. You don't hear much about that pattern being used. I've implemented it once but then it didn't get used in prod anyways.
|
|
|
|
|
David O'Neil wrote: Globals are a tool.
I agree with that. I just think that in Python they made globals to default like that to make it easier for people learning to program. However, I don't think it makes it easier really. It is confusing in a different way really.
David O'Neil wrote: But if I found a place where a Singleton absolutely made sense, I'd use a Singleton
That's good balance. Also, I like a Singleton for app configuration. There really is only one app config but there it is also a good candidate because it is made up of multiple properties which probably means having them all together in one object is nice instead of spread around in the code where you have to look everywhere to find them.
|
|
|
|
|
The Python code you posted looks ugly. I agree with your assessment. My reply to your other point is encapsulated in my reply to Nelek, up above. If it works for you, though, it works. And that's all that really matters.
|
|
|
|
|
David O'Neil wrote: If it works for you, though, it works. And that's all that really matters.
Yeah, I agree to a point. I'm working on some old prod code right now that is written in Java.
Because the original dev didn't understand anything he created every variable as a global.
The code is 2500 lines or so and it does some important prod work that is very simple --- or could be simple if the code wasn't so terrible.
Now you can't tell if you can change the variable you are looking at in the method way down on line 1000 because it may be used somewhere else and you can't tell if your change will kill it.
Side Effects
These are side effects. And they are really bad. The new paradigm of Functional Programming has a main point of attempting to remove all side effects because they are so difficult to manage. In Functional Programming, no function should ever create a side effect. Globals do the exact opposite.
Also, my main point about Python is the way that everything you declare and use automatically gets placed in the global namespace. That will always seem crazy to me.
|
|
|
|
|
raddevus wrote: Because the original dev didn't understand anything he created every variable as a global.
Oh, you poor, poor soul! I can only imagine the cuss-fest! I'd be right there cussing with you! Blame that on HR hiring incompetents! Unless it was created by the owner of the company, then you'd best polish your resume!
|
|
|
|
|
David O'Neil wrote: Unless it was created by the owner of the company, then you'd best polish your resume!
Yeah, it is a tough one. The company I work for was a "Startup" back in '98 or so and basically hit the ground running. Owner hired a "friend who could program" and so a lot of crazy stuff was created.
Slowly we are getting rid of it, but of course it is like changing the wings while flying.
|
|
|
|
|
Stop using Python and rediscover inner peace?
Just a thought!
|
|
|
|
|
Super Lloyd wrote: Stop using Python and rediscover inner peace?
I agree. but it goes back to the fact that lots of Python libraries have arisen out there that let you import and call a function and it does everything for you.
It's like candy for kids. They know they should eat nutritional food, but they keep coming back to candy.
|
|
|
|
|
Globals have a place.
Right next to GOTO.
|
|
|
|
|
Or even ...
def printGlobal():
print(str(extra))
extra = 35
printGlobal()
extra = "Python are stupid."
class Arsinine:
def __init__(self):
printGlobal()
a = Arsinine()
|
|
|
|
|
Exactly! More proof that globals are terrible and cause confusion.
But, I'm sure the Genius-Global-Creating-Devs* can keep track of them in their minds.
*Was a good example of this a soft troll?
|
|
|
|
|
|
Cp-Coder wrote: get a Kindle They are not immune to viruses.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
Cp-Coder wrote: What is wrong with people stupid enough This pandemic has brought the stupid out in a lot of people. The most obvious, in my opinion, are those claiming not wearing a mask is the same as murder.
Some would say microwaving to disinfect might be resourceful.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
After reporting this story, microwaving of library books grows by 1000% as bored lock-ins get ideas.
|
|
|
|