|
Calin Cali wrote: I`m curious to know, c++ hasn`t been around since forever, how was this problem dealt with in the C days? Even the original 1970 Pascal provided a simple polymorphism, through "variant records".
In my first university level programming class, in 1977, the professor made some requirements not mandated by the language:
All data shall be put into Pascal RECORD variables - or class instances, if you like - representing a set of related property values.
All functions/procedures shall take a RECORD instance as its first parameter (although the formal parameter could be named anything descriptive, not just 'this').
Functions/procedures taking a RECORD type R as its first parameter shall be the only ones to modify an R record, and only the instance supplied as first parameter.
The RECORD type declaration shall be followed by all the functions/procedures taking this record type as first parameter.
If one object type is a special case of another one, embed the general RECORD type as the first field in the larger RECORD. For simpler subtype cases, we could use the variant record mechanism.
When C++ arrived 8 years later, we changed 'RECORD' to 'class', moved the closing brace down to after the function declarations, changed 'operation(object, ...' to 'object.operation(...' and changed uses 'object.field' to 'this.field' (or only 'field'). Where subclassing and inheritance was used, the first field type name was moved to a parent class reference in the class definition and the name of the parent class field deleted (e.g. from MyBus.Vehicle.Numberplate to MyBus.Numberplate.) There really wasn't that much change in the programming style, mostly rather minor syntax adjustments.
Obviously, our OO style of plain Pascal programming didn't provide all the mechanisms of today's C++ (nor did the first C++!). No abstract classes, no overloading, ... But we did have multiple inheritance!
(Another but not OO-related requirement this professor made: In any function / routine / method parameter list, the read only input parameters come first, out parameters and references that are modified comes last. To this day, when I see code breaking this rule, I find it terribly confusing and want to edit the order, regardless of who owns the code!)
We never called it 'object oriented' in those days. Nor did those programming the first OS I had source code access to, programmed in a near-assembler-level language in the early 1970s. I saw it after I had learnt C++, and recognized the sub/superclass structures, abstract classes, virtual functions ... except that it was laid out 'by hand' in memory word by word, and the function pointer tables was addressed 'by hand' as the C++ compiler would have done it. When I presented my academic view on it, the old developers shrugged: Well, but this isn't high level language.
In other words: C++ certainly did not invent OO - it just was the first successful attempt to give OO a widely accepted language syntax. (Simula 67 and Smalltalk 72 was less long-term successful in the marketplace.)
|
|
|
|
|
There are a few ways to organize everything on your screen. One way is to use the built-in organizational tools that your operating system provides. For example, on a Mac you can use Spaces to create different "areas" on your screen to keep things separate.
Another way to organize your screen is to use third-party apps. There are a number of these available, and they can be very helpful in keeping your screen organized and tidy.
|
|
|
|
|
Going by your question, "My question is how do you keep it all organized?":
Organization should start with what is most important.
Then to what is next important.
And so on.
That is it. All that answers your question about organization.
For this to work:
Make each of these work. Include error checking to each before moving to the next. Test them each before moving on to the next.
Use switch or if then or whatever code is easiest for you (your personal self) to use and follow later.
It is not so complicated. Just do as I said, one at a time. Take your time. Do not get into a hurry. Do not take short-cuts. Make *your* code readable to *you*.
If you write most of it with simple if-then-else and if that is most comfortable to you, then that is how it should be coded.
Thank you for asking.
Here is an example.
If you have a character moving in a scene with walls and background, then this all has to be rendered to some output.
Remember this is just an example.
First create or load or put together the background.
Then effects to the background, like lightning or explosions.
Then the walls.
Then effects to the walls like splatter eminating from bullet hits etc.
Then the stationary items in the space like blocks or resources etc. which are upstaging the character.
Then effects to those stationary items.
Then movable items or characters that are upstaging the character.
Then effects to those particular movable items.
Then the character.
Then effects to that particular character.
Then do similar to that which is down stage of the character.
Upstage is further away from you than the character. Downstage is closer to you than the character.
Now that I have answered your question as it was asked, I feel like I might now get into other things. The following might be tangental to the question, but I at least answered the question first.
If you are doing this in Microsoft Windows and if you are blitting the images (still or virtually moving), then you might want to use 2 or three or many more buffers, blitting to each buffer as you go from the furtherest away from you to the buffer that is closest to you. Put all of these together and blit to the screen buffer. Then put the screen buffer to the screen.
If you have 5 buffers and the background is buffer_5 then when you have buffer_4 complete, add buffer_4 to buffer_5 and save it as buffer_4. This can be done by starting buffer_4 as a solid color (example RGB 255,0,0 which is Red) and bit block transfering images to it that are like custom cutouts pasted to construction paper. Then blitt that buffer_4 onto bufer_5 with the red area being transparent and save this as buffer_5. Do this until you get to buffer_1 and then blitt that to the screen buffer.
Do not compost to the screen buffer. Just blit a completed buffer to it.
Hope that helps.
Just an example.
|
|
|
|
|
I have a desktop app that consumes a Google API. Right now the Client Id and Secret are defined as constant strings in plain text and built into the app.I'd like to secure them with encryption, but then I would have to store the key somewhere, which doesn't solve the problem.
What's the best way to secure the Id and Secret?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
There is no absolute solution.
Anywhere you get it from the code when running must still have it in memory which could be copied.
Some possible variations.
1. Encrypt text in your code. But then of course the encryption key must be somewhere. But it does make it a bit harder to find the more useful (hackable) first one
2. Load it from a file. Installing into production means that the authorized users are only ones with access to the file. They put the value in the file. This can be combined with the first one so that the value in the file is still encrypted. In that case you do want the encryption key in the code and not the file. Because then they would need to figure out both to get to the uncrypted value.
|
|
|
|
|
Looking at a large project and trying to figure out how it all works I realized that unlike real life software projects don`t have superstructures. It`s all rather scattered/fragmented. Code files have links to other pieces of code via the header files present at the begging of each cpp file and that`s about it.
|
|
|
|
|
I've seen code files with couple of thousand lines and I must say that there is luckily no megastructures as such file are quite complex to reason about, support and put them under test
|
|
|
|
|
CalinNegru wrote: software projects don`t have superstructures. If they a re poorly managed that is generally true. But a well organised project will always have a lot of structure.
|
|
|
|
|
In c things probably aren`t that much elaborate but if we talk c++ is a factory a superstructure? To my mind a factory is the environment designed to handle `well` class instances.
|
|
|
|
|
A factory is a way of organizing certain things based on a certain need.
It applies to most (probably all) Object Oriented languages.
I can also state that although a bit odd you can create something similar in C.
|
|
|
|
|
Quote: A factory is a way of organizing certain things based on a certain need.
You make factory sound like a vague notion, to my knowledge it`s a well defined pattern to create objects.
|
|
|
|
|
CalinNegru wrote: to my knowledge it`s a well defined pattern to create objects. I didn't see where they implied otherwise.
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
why the rhetoric? I wasn`t arguing I was only seeking explanations.
|
|
|
|
|
It depends what you mean by a "factory". The Factory Pattern is a well defined method of creating certain objects, based on a class structure. But you can still write well structure projects without using it.
|
|
|
|
|
What is the default approach for creating objects using a factory? When one is creating several objects of the same class using a factory is the factory class retaining the objects as an array/std container and returning through a function a pointer to the object that has been created (which can be stored into an array/container outside the factory class)?
this is code for creating a single object
#include <iostream>
using namespace std;
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
};
Vehicle* Vehicle::Create() {
return new TwoWheeler();
}
class Client {
public:
Client()
{
}
~Client() {
if (pVehicle) {
delete[] pVehicle;
pVehicle = NULL;
}
}
void BuildVehicle()
{
pVehicle = Vehicle::Create();
}
Vehicle* getVehicle() {
return pVehicle;
}
private:
Vehicle *pVehicle;
};
int main() {
Client *pClient = new Client();
pClient->BuildVechicle();
Vehicle * pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
return 0;
}
how should the modified version of main() look like if you want more than one vehicle to be created
|
|
|
|
|
|
I`ve had a look at Snesh`s profile, thank you.
Quote: That is not really about a Factory, just about creating objects
I know. But things are meant to be learned in a certain order. Factory seems to be the next thing to learn after the "c++ class" lesson. Factory stands for more than just one thing, but those things designated with the word 'factory' although different they still somehow resemble. Basically the factory pattern upgrades the understanding of constructor and destructor concepts. It`s like traditional German house windows, everybody knows Germans are the best car makers. That means they gave a good grip on the things that go into making a car. Germans had the best tanks in WWII so that explains why Germans have a good grip on the concept of car body/frame. The problem is tanks didn`t had windows (and still don`t till this day) so someone arranged things such that Germans have a good grip on the concept of physical windows too, German houses have a two layer windows system (which is basically two windows in one): the usual window made of glass and metal/wood frame and then the wooden only layer/covering meant to protect the windows from physical damage.
|
|
|
|
|
CalinNegru wrote: I`ve had a look at Snesh`s profile, thank you. I meant you to read her articles, if you really want to understand Factories in programming.
|
|
|
|
|
Thanks.
|
|
|
|
|
Some projects are as you describe. The only way to analyze dependencies is by #include directives, which aren't even reliable. Ones that aren't needed don't necessarily get removed. And others that should be added aren't, because the header in question gets accidentally included, transitively. Sometimes A.cpp #include s B.h, and B.cpp #include s A.h for reasons of collaboration. Such circular dependencies are sometimes unavoidable.
Layering is the main way to impose higher level structure. The software is organized into static or dynamic libraries that preclude circular dependencies. That is, if library B has a file that #includes a file in library A, then no file in A can #include anything in B. This allows libraries to be tested independently and also allows an application to be developed without having to use a monolithic code base that contains various things that the application doesn't need.
|
|
|
|
|
CalinNegru wrote: Looking at a large project
Depends on what "large" actually means...
In the real world companies end up with software that was created by many people over time.
As with everything else that humans are involved in quality tends towards the average. That includes design which impacts what you refer to as 'structure'.
Programmers also like to think that they know for certain that the best way to do something is the way they know. Which is completely subjective.
So they create new 'better' solutions willy-nilly and hack them into existing code bases because of that. Then they leave the company and someone else starts doing it. Overtime this leads to significant organizational problems.
Even in the best systems there are real world business requirements that only come up long after the original design and for which the original design did not account. And the company is not willing to pay to refactor the entire code base when this happens. Even worse if it wasn't well designed. Or with 'better' ways on top of it.
And developers seldom consider the long term impact on maintenance when they make radical decisions to go in a different direction on a code base. It is known (multiple studies) that maintenance costs are always 2 to 10 times higher than the original cost to develop the product. And 100 times higher is probably reasonable for some.
Might note that although I point out developers in the above I have never seen a company that was actually willing to recognize the maintenance costs much less put an emphasis on mitigating for that.
|
|
|
|
|
Background
I have a WPF app in which I'm using DevExpress Reporting.
To create a report based off a List<t> there is a wizard which allows you to choose "Object Data Source". When you choose that you see a list of entities in your app that are marked with the attribute "[HighlightedClass]". This attribute is defined in the namespace "DevExpress.DataAccess.ObjectBinding".
My WPF UI, DAL, BL, and entities are all defined in seperate projects. This all works fine.
Problem
Now I'm working on a Xamarin Forms project that will use the same DAL, BL, and entities to pull data from the WPF project into an Android app.
My shared mobile project has references to the DAL, BL, and entities. And this is where the problem is... when I deploy to the Android I get deployment errors saying that the Android project can't resolve references to DevExpress assemblies.
I'm sure that if I were to remove the "[HighlightedClass]" attribute from the Entities project then everyting would deploy fine. But then I would not be able to create new reports in the WPF project.
Possible Solution
One idea I have is to create local models in the WPF project for reporting. My UI project could call back into the back end, get back a list of data as LIST<t>, them map them to local models which would use the attribute. This way the attribute only appears in the WPF project where the reporting happens. The Entities project would no longer know about DevExpress. And the Android app would no longer complain about it.
But this is a lot of work and could create maintenance headaches as I would have local Models that are exact duplicates of the Entity classes in the Entites project. I would have to make changes in two places.
I'm open to suggestion here.
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Have you considered creating your own [HighlightedClass] stub attribute in the correct namespace that could be used as a stand-in reference in the other project?
It would just need to be compile compatible with the real class.
Or possibly even it is compiled as a source only attribute in one context…
This leads to a scenario where you might want the same source to be shared across two different projects so it can be compiled two different ways?
Or use it as a binary dependency? You have 2 versions of a DLL?
|
|
|
|
|
Like a Halo ring, or a Dyson Sphere? Just want your thoughts on megastructures.
And if you are not a Halo fan, go by Larry Niven's Ringworld.
|
|
|
|
|
Tagged you as a troll for posting OBVIOUS off-topic, bullshit questions in the programming forums.
modified 29-Dec-21 9:49am.
|
|
|
|