|
Marvellous. I thought all the humour had gone from programming and everyone was an accountant.
Reminds me of the old DDJ obfuscated C competition. For those younglings unfamiliar with this, DDJ was a magazine (like a web site but printed on paper). Check out http://www.ioccc.org/.
|
|
|
|
|
Take it somewhere else; it's not an article.
|
|
|
|
|
I'm so glad for you that you were so lucky not to work with those "rumorous" C# developers.
But I'm not.
Being running .NET projects for 7 years already I've met a lot of them. Sure they didn’t pass my filters on interviews, but there are a lot of other chances for such guys to sneak into your project: from an offshore partner, departments’ rotation, joint projects, etc. And when you talk with such person he doesn’t seem to be completely dumb. But he has his own picture of the world. And nothing can change it!
I really hope that such guy will find this article some day and will understand at least 10% of what I’m trying to say.
|
|
|
|
|
Hey dude, lighten up.
Lots of articles in this forum are a waste of time but are presented as you beaut good ideas.
There ARE some valid insights in this article and it also made me laugh - not bad.
Peter Wasser
|
|
|
|
|
Yes, I couldn't agree more. All articles should be strictly educational, informative, and as dry as possible.
There's no laughing in programming!
|
|
|
|
|
Using code region makes your code better organized, BUT
using empty code region makes your collegues imagine that you're full of ideas to write.
#region "Public methods"
#region "User Interface"
#end region
#region "Interprocess functions"
#end region
[...].
#end region
|
|
|
|
|
Do we really need another one of these articles on the internet? Write it on a blog somewhere where all tired and re-hashed jokes exist.
|
|
|
|
|
I like it but I find it hard to believe you can predict other programmers biases. I'm lucky if I now my own likes and dislikes.
|
|
|
|
|
Reminds me of a range of articles I wrote decades ago named 'Cryptomanic programming'. It was a tutorial how to create non-understandable code. Some ideas I worked out there:
- Fiddling with ++ (pre and post),+=, <<,>> operators. It's not so difficult to create one line of code that is hard to understand.
- assign more then one variable on the same line. For example: a=b++=c
- changing the variable of a for-loop in the loop itself (different languages have different implementations for this.) You can also change the upper boundary of the for-loop within the loop, and of course the stepsize.
- If your language has macro-capabilities (I don't know C# very well) there are great possibilities to hide things. What i understand of C#, delegates would be my candidate. The C-variant is to use pointers to functions whenever you can. Pointers to pointers to data is also much more sexy as direct datatypes.
- Use the automatic conversion of numeric types for your benefits. Cast to whatever datatype. Floats are my favorite because there's no standard between compilers defined. With some fiddling you can make a program that will (maybe) compile on another compiler but will give strange results. Cast dates to floats and v.v. for example.
- Most high level languages use underlying pointers to implement objects, strings and so on. A great opportunity for the clever programmer. If you can mingle these references with pointers you will get spectacular results.
- A simple but effective advice: use as many variables as you can. And if your language supports untyped variables use them as much as you can.
- Create global variables; they are much easer. Don't forget to create local variables with the same name as the global ones now and then.
- Recursive methods are sexy, they look impressive and nobody understands what they do. Use recursiveness whenever you can.
- return values of functions and methods are intriguing. Maybe you can return a pointer to a local variable.
- Never, never trust a variable. Don't use a variable without checking if it has the right value first. This is surely true if a variable is used as an argument to a method but also within lenghty methods. You never know what happened since your last assigned it a value.
- If your language supports it use 'short-cutting' whenever you can (the effect that if a or b, and a is true b is not evaluated anymore.) Remember expressions may include invokation of methods also.
Some more:
- Never use a DBMS, write your own instead (that is much more efficient and keeps you of the streets).
- XML is hot, never write anything to disk if it is not in XML.
- Use standards. Seek for the most complex one's and augment them with your own solutions. Point is: noone understands them, but you can always say to your boss that the standard requires ... (fill in whatever you want).
- If you use OO: objects need other objects, so create a system that has as many objects as you can think of. The truth is: everything is an object so get rid of variables and turn them into objects. And objects need to work together, so move methods of one object to an object of another class (warning: this is not so easy as it sounds, but try it). Try to make objects that are max. depend of other objects.
- If your language supports multiple inheritance: feel free and try this concept to the max.
- Forget the stories about reuse. Copy and paste as many code as you can. Reuse is only usefull if you have to change the method/class/function to get it work.
- A professional project uses at least 15 Dll's.
- Versioning: If you want to change something on a method or function (for example because it has a bug) keep the old version in your system (who knows where it is good for in the future). Copy the method to change and give it a new name. By the way: in practice it is always good to have redundant code in your project. And don't forget to create methods that are never invoked.
- Versioning (2): a very sophisticated concept is creating Dll's that contain the same methods but are of a different version. For example create a Dll with some methods. When you create a new release copy the Dll, do your changes in this one, and release this one also. In you main program dynamicly load the version of the Dll you need (the one with bugs or the one without).
That's it so far. If you need more feel free to ask: I have tons more...
Rozis
|
|
|
|
|
This is great.
I like versioning approach.
|
|
|
|
|
Brilliant ideea man!
This should be best article of January. I mean it.
Maybe this helps too:
if(!(!(false && true)))
modified on Monday, January 11, 2010 7:21 PM
|
|
|
|
|
Thanks.
Waiting for votes.
|
|
|
|
|
For 6. Write less code:
Are you sure you want to pass SQL query as a query string?
Regards,
Pratik
|
|
|
|
|
Me not, but "rumorous" developers sure could use it.
Please, read disclaimer.
|
|
|
|
|
In addition to using single letter variables to save on both typing and disk space, you should make use of using to create single letter aliases for your most commonly used classes:
using S=System.String;
Note that S is perhaps not the best character to use in this instance, as it is a common letter that you may need for something else. Use a letter that is less likely to be required, such as Q or H. Alternatively, you have the entirety of the Unicode page set to choose from!
If you choose to go down this path, I recommend using an extended Unicode character that looks exactly like an existing Latin alphabet character. This will help those new to your code to feel more at home. Cyrillic is particularly rich in these.
Also, avoid those complex if...else and switch clauses by making use of nested ternary operations.
Eliminate all unnecessary whitespace. It is inefficient, and without it you won't need to strain your eyes or mouse-scrolling finger as much, as the code is all in one place instead of scattered all over the unit.
Save on memory and typing by re-using variables. Never declare a new variable if you have a perfectly good one that isn't currently being used! A smart programmer can even find ways to re-use variables that are currently in use.
The following code demonstrates some of these techniques, and more!
using System;using System.Collections.Generic;using S=System.String;using C=
System.Console;using I=System.Int32;class L{Dictionary<S,S>d=new Dictionary<
S,S>();I p=9,b=999,g,u,v,i,j,c,x,y,G,K,X;S a="@",w="#",f=".",s=">",m="M",W=
"W",J="T",o="!",O="o",U="*",H="0@0",t,A,M;List<S>e=new List<S>(),z=new List<
S>();Random r=new Random();L(I h,I l,I k,I D,I E,I Q){G=l;x=D;y=E;X=Q;h+=l;K
=b/2;c=b*(l>5?5:l)*3;while(g++<c){t=(R(b)-K)+a+(R(b)-K);e.Add(t);d[t]=R(b)<l
*2?J:R(14)<13-l?W:m;}c=0;for(;;){M=" ";u=x;v=y;c-=96;x+=c>0?(c+2)%3==0?-1:c%
3==0?1:0:0;y+=c>6&&c<10?-1:c>0&&c<4?1:0;t=T(P);if(e.Contains(P)&&(d[P]==W||(
d[P]==J&&R(3)<1)||R(4)<3)){e.Remove(P);k+=d[P]==J?2:1;if(k%9==0||d[P]==J&&(k
-1)%9==0){h+=l;M="Lvl!";}d[P]=f;}if(t==o){h+=R(l)+1;t=f;M="Heal ";}if(t==U){
X=++Q;t=f;M="L.orb";}if(t==O){M="ORB!";return;}if(t==s){M=new L(h,l+1,k,x,y,
Q).M;return;}if(t!=f){x=u;y=v;}t=u+a+v;d[t]=f;for(g=0;g<e.Count;g++){i=N(e[g
],0);j=N(e[g],1);A=e[g];u=i<x?x-i:i-x;v=j<y?y-j:j-y;if(d[A]!=J&&(u>p||v>p))
continue;t=(i<x?i+1:i>x?i-1:i)+a+(j<y?j+1:j>y?j-1:j);if(t==P&&R(3)<2)h-=R(d[
A]==J?l*2:l)+1;else{if(d[A]!=W&&(T(t)!=f||t==A)){t=(i+R(3)-1)+a+(j+R(3)-1);}
if(t!=P&&T(t)==f){d[t]=d[A];e[g]=t;d[A]=f;}}}if(h<1){M="Dead ";return;}g=p*2
-1;C.SetCursorPosition(0,0);for(j=0;j++<g;){for(i=0;i++<g;){var q=(i<p?p-i:i
-p)+(j<p?p-j:j-p)<p&&i>2&&i<g-1&&j>2&&j<g-1;A=(i-p+x)+a+(j-p+y);var B=z.
Contains(A);if(q&&!B)z.Add(A);u=l;while(u>13)u-=13;t=T(A);u=q?A==H?13:t==w?u
<1||u==7?14:u:t==f&&A!=P?l==13?5:7:15:8;F=u;C.Write(A==P?a:q?t:B?!e.Contains
(A)?t:f:" ");}C.Write("\n");}F=15;C.Write("L"+l+" H"+h+" X"+k+"\n"+M);if(Q>0
)C.Write("\n"+P+"");c=(I)C.ReadKey(true).Key;}}S P{get{return x+a+y;}}S T(S
c){I D=N(c,0),E=N(c,1);return d.ContainsKey(c)?d[c]:d[c]=D>K||D<-K||E>K||E<-
K?w:c==H?G>12?O:f:G<13&&R(b*9)<9?s:R(b*2)<2?o:X<1&&G>7&&R(b*9)<3?U:R(9)<7?f:
w;}I R(I i){return r.Next(i);}I N(S c,I i){return I.Parse(c.Split('@')[i]);}
I F{set{C.ForegroundColor=(ConsoleColor)value;}}static void Main(){C.
BackgroundColor=(ConsoleColor)0;C.Write(new L(9,1,0,1,0,0).M);C.ReadLine();}
}
|
|
|
|
|
This is brilliant.
You can save money on obfuscator! Your code doesn't need it.
|
|
|
|
|
In addition, you can save money on recruitment! Simply hire only those who can precisely state the operation of code written in this more efficient manner. Ten minutes should suffice given the sample listed above, however if recruiting for an intermediate or senior role then five should be plenty.
If you are allowing them to actually view the code sample while deducing its operation, rather than beforehand, cut the time in half, as this makes the problem trivial.
|
|
|
|
|
Man, this is genius. Seriously.
|
|
|
|
|
Thank you, but I don't feel I should have to take the blame, you started it.
Of course, for maximum efficiency one would combine the above tips with the use of a non-managed language, allowing you to reference and dereference pointers/bit shift etc.
However, for those forced for one reason or another to use a managed language such as C#, at some stage or another you will find that even code samples such as the above reek of inefficiency.
At this stage, it is time to write your own pre-processor.
I have started implementing one with the working title of Tercshe, a portmanteau of terse and csh.
By forgoing needless restrictions such as being "context-free", which are imposed on currently popular languages by incompetent computer scientists in order to keep them in work publishing papers, giving lectures, writing books and all of those other academic trappings, Tercshe allows for extremely concise, clear and efficient code, as illustrated by the following sample, which after translation to C# by the pre-processor looks much the same as the C# sample given above:
DSd;Ip9b999xyguvijclkhc~;Sa"@"a~"#"f"."s">"m"M"tb~d~;Rr;LSe;n{g0;e-;d-;@g+<b
*l*2{t((rb)-499)a((rb)-499);e+t;dtm;}doa;@{ux;vy;gc-96;?(g2)%3{x-;}:g%3{x+;}
?g>6&g<10{y-;}:g>0&g<4{y+;}d~o;tq;?tm{e-o;dof;k+;}Z;?ts{l+;n;^;}?t!f{xu;yv;}
d(uav)f;doa;@g+<eC{b~eg;c~0;iw;c~1;jw;u?i<x{i+;}:i>x{i-;}v?j<y{j+;}:j>y{j-;}
t(uav);d~t;?qf{egt;dtm;d(iaj)f;}?qa{h-;}}?h<1{^;}g(p*2-1);@j+<g{@i+<g{d~(i-p
x)a(j-py);tq;u?ta~{l;}:{7;}@u>15{u-15;}F?u<1{u;}:{7;};Wt;}N;}F7;N"L"lf"H"hf
"K"k;Gc;}}So{^xay;}Sq{^?dKd~{dd~;}:rb*9<9{s;}:r9<7{f;}:{a~;}}Iw{^IPb~S"@"[c~
];}l1;h9;k0;n;E;
|
|
|
|
|
My eyes are broken.
This code reminded me a crying situation with one project where we had to reverse-engineer 120Kb of Javascript library with hardly obfuscated code. It ended-up with finished job and finished developer - he got drunk to dead.
|
|
|
|
|
</satire>
I'll stop being funny for a moment. That sounds positively deadful, like you may have been better off just doing a rewrite!
The C# sample above is real code that runs (it's a very crude Roguelike game - create a new console app and replace the contents of program.cs with the above to see it in action), I created it for a minimal code challenge that was being run in the rec.games.roguelike.development newsgroup. The version above is 2kb of C# code and was the successor to the one I wrote for an earlier 1kb challenge.
I thoroughly enjoyed it, as it required a very different mindset to "normal" programming. It was a matter of constant refactoring trying to find tricks to further reduce the size of the code base to add more features.
The best ones in the challenge were those written in C using all sorts of weird pointer referencing/dereferencing/bit shifting tricks that mostly went over my head (and indeed would only compile properly under certain compilers using certain switches!).
The Tercshe stuff was something I played with briefly to try and squeeze even more bytes out of it, but I decided that it was too much effort.
|
|
|
|
|
I really appreciate all your input.
My kudos for being so minimalistic! I'm impressed that this is a playable game.
I wonder how much C code the winner has?
|
|
|
|
|
Single letter variable naming keeps your code concise and your program file size small!
|
|
|
|
|
also, it adds that built in limitation of 26.
|
|
|
|
|
Nah, you can use uppercase also! (but who needs 52 variables???)
|
|
|
|
|