Michal Kohutek

Copy-Paste Driven Development and other techniques for speedy programming

An ironic article how not to write code

Some people write code that works, but I am not quite able to understand why and how. They seem to use practices I am unfamiliar with. To deal with this problem, I have decided to reverse engineer this secret handbook they used to learn programming. Here are my findings.

Copy-paste Driven Development

This is an extension of the powerful optimalisation technique known as loop unrolling. It makes your code easier to design, uses less variables (saving precious processor cycle) and best of all, it allows you to easily produce hundreds of lines of code per hour. Even programmers who call themselves elite can’t produce that much.

To start, you need to know two code shortcuts, Ctrl+C and Ctrl+V. It may be slightly different in vim. Now, instead of using CPU hogging workarounds for lazy writers like for, you just copy it and paste it several times. Then you edit some variable names or indexes. Here is an example:

class MyClass78 {
public:
	Myclass27* pwb1; // The upper PWB
	Myclass27* pwb2; // The lower PWB
	Myclass27* pwb3; // The leftmost PWB
	Myclass27* pwb4; // The PWB roughly at the centre
	Myclass27* pwb5; // The PWB at the left-down corner
	MyClass78() {

	}
	void SetPwbs(Myclass27* arg1, Myclass27* arg2, Myclass27* arg3, Myclass27* arg4, Myclass27* arg5) {
		pwb1 = arg1;
		pwb2 = arg2;
		pwb3 = arg4;
		pwb4 = arg3;
		pwb5 = arg5;
	}
};

It also conveniently prevents you from destroying too much of your work if you accidentally delete something you haven’t yet synced with Google Drive or find you had deleted it before the last sync. If something is deleted, you can find a similar part that looks like copied from the deleted part and make some small edits.

Another advantage is that it makes your code nearly impossible to edit. Don’t let others trick you into making your code editable – they want to reuse the code you have so laborously written. Make sure they cannot use even a bit of it.

This leads us to another advantage of this approach. You can make your code open source, enabling your program to use a lot of free libraries, without fear that some competitors would steal your code. If you follow the other rules, they will not even figure out how you solved the problems you are both facing.

One object to rule them all

So you have a lot of functionality that is all done by objects that are one of a kind? This pattern will save you from the nuisance of passing the references all around the code, improving performance and reducing the amount of code, but most of all, it saves you time by making everything available so that you won’t have to look for these instances in other classes should you need it.

This object is basically a long main() function turned into a class because the stuff in main() is hard to access from other objects (in case you have some). If you will need to have some of its many functionalities more than once, you can just copy and paste it and append 2 behind the name of the new one’s members and methods.

If the file grows too big and becomes hard to navigate, remember that nothing prevents you from saving it into multiple .cpp files. This also makes the restoration of backups from a USB stick or Google Drive more convenient.

I am not including an example because most computers don’t have enough memory to open a page that contains one.

The traditional array

Some practical programming languages like MATLAB index arrays from 1. This is a serious design problem of C++. You can have them using this simple trick:

floatArray makeMatlabArray(int size_Int) {
	return new float[size_Int] - 1;
}

//...
floatArray floatarray = makeMatlabArray(28);
floatarray[28] = 1.5;

The deathclock

Sometimes, the pointer structures are so complex that no one can know when they should be deleted. Here comes the Deathclock Pattern. You can estimate the longest time it will live and start a thread that will delete it when done.

pwb1 = new myClass37(ay, 13, ablInd, qw, myclass17Inst);
std::thread a([=]() {
	sleep(100000); // Ought to be enough for everyone
	delete pwb1;
});
a.detach();

The big warning

It may happen that your class has an attribute that can break the object’s functionality if edited carelessly. To make sure it’s only read and written into only in one of the permitted ways, you can write a big warning:

public:
int portaddress; // Write here ONLY if the communication is
                 // stopped, its cache IS DELETEd (DON'T forget
                 // to delete also its sum object) and you HAVE TO
                 // start the communication again AND SET the global
                 // named L to value 17

The lovebirds

Because you should code with love, your classes should also love each other. They should use each other a lot so that they would be as unseparable as lovers should be. This is hard to implement in most languages, but in C++, it is possible:

// header 1
struct Myclass18;
class MyClass18 {
	Myclass18* lover;
	void assign(Myclass18 *lovIns_);
	float cooperate();
};

// header 2
class MyClass18;
struct Myclass18 { // Why havent I discovered before that struct doesnt
                   // need ths stupid public: keyword?
	MyClass18* lover;
	void assign(MyClass18 *lovIns_);
	float cooperate(float num11);
};

// source 1
#include "Myclass18.hpp"
#include "MyClass18.hpp"

float MyClass18::cooperate() {
	return 7 + lover->cooperate(L);
}

// source 2
#include "Myclass18.hpp"
#include "MyClass18.hpp"

void Myclass18::assign(MyClass18* lovIns_) {
	lover = lovIns_;
}

float Myclas18::cooperate() {
// Indentation is a waste of time, this isnt Python
float b = lover->cooperate();
if (b < 400)
return b;
return 5;
}

The other main

Sometimes, it’s handy to have the program start at various places, because main() is already too complicated and it’s better not to touch it anymore. There comes the technique to make alternative main functions. They can be made to start using this trick:

bool allother_mains_haverun() {
	main2();
	main3();
	main4();
	main5();
	// Add other mains here
}
// The stuff below must be a global or it won't work
bool allother_mainshaverun = allother_mains_haverun();

The Adam class

Also can be called The Elder Class or The Precursor Class. It is one class that all your classes inherit from. This allows you to store any class in a vector. You can check what type it is using its type member. It is easy to implement:

enum classType {
	NONE,
	INT,
	STRING,
	//...
};

class TheGreatOldOne {
public:
	enum classType type;
};
std::vector<TheGreatOldOne*> allObjects;

class MyClass11 : public TheGreatOldOne {
public:
	MyClass11() {
	}
	void initialise() {
		type = MYCLASS11;
	}
	//...
};
// This is the awesome trick you can do now
std::vector<MyClass11*> getAllOfMyClass11() {
	std::vector<MyClass11*> valueToReturn;
	for (unsigned int i = 0; i < allObjects.size(); i++) {
		if (allObjects[i].type == MYCLASS11) {
			valueToReturn.push_back(static_cast<MyClass11*>(allObjects[i]));
		}
	}
	return valueToReturn;
}

This allows you to obtain any object from anywhere, without having to resort to improvised solutions like keeping extra references in the objects that need them.

You may have difficulties to store classes that come from other libraries (like STL) in a vector with other types. It can be easily solved using this approach:

class MyVector : public std::vector<TheGreatOldOne*>, public TheGreatOldOne {
	void initialise() {
		type = VECTOR;
	}
};

This can be pasted into any header or source that uses such a class. It may cause compilation errors, but you can number them MyVector1, MyVector2, MyVector3 et cetera. As long as their declarations are the same, they all can be downcast to any of them and it will work.

With some more tricks I will provide on demand, you can make a very natural and human readable way of accessing the object you need from whatever place in your program:

int number = select(&MyCls15::pgt).from(MYCLS15).where(&MyCls15::m4, EQUALS, 12);

The unconst method

So there is a place where the library returns your object, but it’s const. You need to edit it. So what do you do? Declare all methods as const and cast the constness away!

int saveUnloadReloadAndInitalise(std::stirng& Filename) const {
	std::ofstream o(Filename);
	o << const_cast<MyClass35*>(this);
	delete const_cast<MyClass35*>(this)->cache;
	delete const_cast<MyClass35*>(this)->Preferences;
	std::ifstream i(Filename);
	i >> const_cast<MyClass35*>(this)->Height;
	i >> const_cast<MyClass35*>(this)->Width;
	i >> const_cast<MyClass35*>(this)->Canvas;
	const_cast<MyClass35*>(this)->Preferences = new preferences(Height, Width);
	const_cast<MyClass35*>(this)->cache = new Cache;
	return true;
}

The Puzzle

Programming is about logic, so programmers love puzzles. Programming can be hard work, so better provide some amusement to your colleagues to give them a breather from all that copying/pasting/renaming. You can do this:

// You have 12 balls of different colours. 1 of them has a different
// weight, it can be more, it can be less. You have a balance to
// compare the weights of two groups of balls, so they can be either
// of same weight, or the ones on the left are heavier, or the ones
// on the right are heavier. How can you find the one with different
// weight if you can use the balance only three times?

However, their boss might not allow them such fun, so you can force them into it by making sure the answer to the puzzle is required to use the code. In that case, they cannot avoid it and the boss must allow them to have some fun. So this is a better puzzle:

enum answerToPuzzle14 {
	MR_TRUTHFUL,
	MR_INDECISIVE,
	MR_LIAR
}

// To call this function properly, you have to select one of the
// three values of the enum above. To learn the answer, solve this
// puzzle:
// Three men sit on a bench. One of them is Mr. Liar who always
// lies. The other is Mr. Indecisive, who sometimes lies, sometimes
// tells the truth. The last one is Mr. Truthful who never lies. You
// ask the first of them who he is.
// First man says: I am Mr. Liar.
// Second man says: He is Mr. Indecisive.
// Third man says: He is Mr. Truthful.
// Who is the second man?

double calculateBessel(Besselarguments* ba, answerToPuzzle14 atp);

This will certainly refresh them before they use your function in their code, so that when they use your code, they will certainly enjoy it more!

Creative naming

Show others that you have thought a lot about the code and give your functions, classes and variables creative names. This is a simple case:

HarrysBestFriend = new MyClass20(((1 + 1) * 3 + 4) * (5 + 2 + 3));
HarrysBestFriend.type = MYCLASS20;
allObjects.push_back(HarrysBestFriend);

Do you get it? HarrysBestFriend is a variable representing cargo of type rum, which is ron in Spanish and Ron was Harry Potter’s best friend!

A smart person speaks many languages

Suppose that you know three foreign languages: English, German and Russian. You are super educated and you need to show it! Unworthy people with insufficient education often speak fewer languages, won’t figure out what you meant. You certainly don’t want them those plebs to touch your precious code. This can also be used to create more variable names, more classes without having to think about new names – you just write the same names in another language. Here’s an example how you can do it:

class MeineKlasse3 {
public:
	// Ета класса в двух структурах, так у неё два родители и два ребёнки
	std::vector<MyClass58> children;
	std::vector<Myclass43> kinder;
	MyClass57* parent;
	MojaTrieda4* eltern; 
}

Efficient use of -fpermissive

When compiling on GCC, you should use the -fpermissive flag. It causes your code to compile if the compiler can understand it. Compilation failures due to petty erros slow you down. It saves you from a lot of const_cast or static_cast uses you would otherwise have to labourously write. The -w compilation flag improves this further, because it removes all those annoying warnings, cleans up the compilation output and allows you to focus on problems that actually matter.

Leave a Reply

Your email address will not be published. Required fields are marked *