Ask Slashdot: What Are Some Bad Programming Ideas That Work? (infoworld.com)
snydeq writes: Cheaper, faster, better side effects -- sometimes a bad idea in programming is better than just good enough, writes InfoWorld's Peter Wayner: "Some ideas, schemes, or architectures may truly stink, but they may also be the best choice for your project. They may be cheaper or faster, or maybe it's too hard to do things the right way. In other words, sometimes bad is simply good enough. There are also occasions when a bad idea comes with a silver lining. It may not be the best approach, but it has such good side-effects that it's the way to go. If we're stuck going down a suboptimal path to programming hell, we might as well make the most of whatever gems may be buried there." What bad programming ideas have you found useful enough to make work in your projects? Don't be shy or ashamed, we all want to hear your responses!
I won't even call it a "bad programming idea". I've seen more problems from over normalizing a database than from under normalizing.
Maybe the bad idea is trying for fourth normal.
using assembly language to code a web page because the boss wanted it to be fast
10 GOTO 20
20 GOTO 10
Goto. I use that (in C) for error handling all the time, and frankly, it is about the cleanest way to do it I have seen.
In theory, practice and theory are the same. In practice, they're not.
$PHP
Every new software, platform, framework, library, protocol, language, compiler... is rife with shortcuts (by design or accidentally) which are, relatively speaking, considered 'bad programming ideas' from generations of folks who did not prioritize them previously. So every modern program basically sucks for the same reason.
I maintain a large old project that's full of spaghetti code. An IDE helps to manage it and it works fine but it's a pain to make certain types of changes.
While it's great for reporting, It will never be a good fit for real applications. When I say real, I mean the ones that you use to actually get work done and not browse kitten videos. Modern use of HTML/JavaScript is the worst example of shoving a square peg into a round hole that I've ever seen... and yet, with enough effort, we make it work.
Frequently run into it, where I have a data set that is small, but difficult as hell code in such a manner as to go through efficiently. So, I can spend many hours trying to get the efficient code right, or just use the much simpler more brute force approach which will still get the task done just a quickly to the user's perception.
C++ Template Metaprogramming FTW.
For when it absolutely positively has to squeeze every last instruction cycle, and screw the next guy...
I wish I had a good sig, but all the good ones are copyrighted
There aren't any bad programming ideas that work.
Coding in Javascript, PHP and VB6.
The world's burning. Moped Jesus spotted on I50. Details at 11.
There's a lot of cases where you end up doing something that is considered not "best practice" and is frowned upon, but it gets the job done, is not likely to cause headaches for future developers, and is the most efficient way to solve a problem. It's not programming, but using !important to force a style when you absolutely have to or to override a bad implementation of bootstrap is a surefire way to solve an issue.
Sometimes unit tests can be extremely helpful. Other times they're a waste of time and provide little to no benefitâ"like when you're only writing them because somebody wants 100% code coverage.
and Matlab ....ffffffFFFFFFFFUUUUUUUU..........!
enough said.
Seems terrible because you become less productive, but with the overhead of communication with a larger team, it's still much more efficient than hiring more people.
You've been there: You have a loop with a conditional. You need to work out if the loop ever took the conditional while(X) if (Y) Z; if (Z not executed) then ... . So you have to set a boolean flag and test it when you break out. It's really clumsy. Python has a nice feature for this, a while ... else , which I haven't seen other languages. Until others do it, a goto is hardly beautiful but less clumsy.
Or really file systems in general, but most of the modern ones has directories. File systems try to seem like a general purpose database abstraction, but using a filesystem to access data is really fraught with peril.
“Common sense is not so common.” — Voltaire
It works.
I've occasionally relied on enumerations being particular values, as a shortcut. Makes me feel icky, tho.
Throwing an exception with a completely empty catch block.
Or rather forget about what's business logic and what's not - if it can be done in the database, do it there.
bite my glorious golden ass.
Sometimes I tell "standard" code formatting to take a hike and do things like:
switch ( something ) ....
{
case 1: { blah; break; }
case 2: { bleh; break; }
}
Not often, but on occasion if you have to deal with a whole bunch of cases and don't want your code spread over 20 screens it's good to condense and align instead.
Few programs are more hellacious to write and maintain than code that has been overly-factored into classes, that inherit from other class, that implement some abstract that was inherited from other abstract, that isn't even called directly because it is actually a event handler or intent for yet another inheritance mess. OOP makes sense if used sparingly, if not, it makes GOTO spaghetti look sane.
... despite that I keep telling them not to, but never good enough to save their business plan or their company from disregarding my wisdom.
- Agile/scrum, anything related to it, inspired by it, or even remotely like it, and the mindset of managers who advocate it.
- "continuous integration"
- "devops"
- server-side javascript
- giving every single person in the IT department the root server access
- using microsoft "solutions"
Javascript on the server side, coming soon to your bank account.
For a while the mantra was that you only return from a subroutine in one place, at the bottom.
I think that's been pretty much abandoned. Return when you're done; don't go through contortions to get out of nested loops or IF statements just so you can get to the return at the bottom.
A horribly inefficient but completely reliable way to sort things.
Javascript, the worst possible programming idea that seems to unfortunately work.
Microsoft Windows.
Some people used Tcl because for a while, it was the only way to use Tk, and Tk was handy. But people who used Tcl for the sake of Tcl shouldn't be watched over, for their own good.
Am I part of the core demographic for Swedish Fish?
No, really - I'm not making this one up. MUMPS manages to find every possible bad coding idea and make it as easy as possible. Interpreted code, typeless data, naked array references, zero FS compatibility with anything . . .
"marketing is a bad idea that works, but in brazil it only sucks" - me.
Sometimes you just have to do it.
I once discovered that an interpretting parser was faster than a compiled version of it. Probably because the compiled version became so large that it was larger than the CPU caches, causing lots of reads from memory, while the interpretter did not. It is often the case that interpretting is fast enough and that there is no need for compiling (to machine code or virtual machine).
I feel bad every time I think about this, but the thing I've written that has had the greatest utility for me personally was some utilities to improve copy-and-paste. Maintaining case (all-upper, all-lower, camel), creating a new file by replacing in the filename, copying one template to a bunch of targets....Sometimes it feels like most of my job, when I'm given something new to write, is finding the closest thing to use as a copy target. So much boilerplate in our classes...If pressed, I know what most of it is for and I can identify what pieces might be missing to cause some unexpected problem, but most of the time I just want to find something that's got all the right bits already and make a duplicate of it.
Magic numbers save tons of time. You get to working code quickly to verify your algorithm. They nev
>Segmentation Fault
The basic for loop is terrible.
Generally with javascript //this works great, as you utilize the items in functions etc they stay set in memory, FANTASTIC
$.each(array,function(index,item){
});
for(var i=0;iarray.length;i++){ //this pile of filth when referenced is unable to do anything but hit the last item in the array when utilized with functions //damn it's creator and his lazyness, DAMN HIM TO HELL! (and yes it was a him, be real)
}
Still though it is a malignant cancer within the code and for new coders the for loop is the go to (until after suffering they are reborn), it does do certain jobs admirably.
switch(true) {
case $a < 5:
do something;
break;
...
}
A bit messy, but a lot cleaner than a stack of if/then/else for a set of of conditions.
An oldie, but goodie unmaintain
Of course, doing the opposite is the tongue-in-cheek point.
On more than one occasion I've been able to write a C solution to a problem where the "high level language" solution only took a few minutes to write, but it took days longer to run than the C solution took to both write and run.
I long for the Web 1.0 days but with modern day bandwidth. ...and while we're complaining...over architected IT systems...."everything is an object/service" is the bane of my careear. I'm learning to appreciate simple pipes and filters more and more every day.
See subject.
Foam at the mouth all you want, in your heart you know it's true.
Enough said.
In 40 years I've used dozens of languages, the only one I learned to actively hate was Javascript/ECMAscript. A pathetic, piss poor excuse for a language.
I've heard PHP is just as bad but, as I've never written anything in PHP I'll give it the benefit of the doubt.
Everyone knows how to input data into a speadsheet, and do useful post-processing in a spreadsheet.
If you use short variable names for loop variables and stuff, you can code faster because you type quicker. Also globals aren't bad, and public variables aren't bad.
I've been dwelling the past months in my team's will to go full-fledged MVC (actually MVP) while developing for the Android SDK (for those out of topic: making apps). I see peers and myself struggling with old, large activities, running laps around to make them pass "technical debt" code reviews intending to "make them more future proof".
It would be nice and all if I could grasp the benefits, but the problem is three-fold:
a) the team is fooling themselves and the company into spending too much resources in something they can't assure adds value;
b) Android already has a very solid MVP-like pattern going on, and MVP-ing it up further is a clear case of overengineering
c) most important of all: there is no actual standard to guide the team, so it's a free for all and I see all the initial benefits down the drain just because everybody tastes a different flavour of the view/presenter combo
And I see and underlying problem which might even be more crucial: the app will likely be dropped before reaping the long-term benefits, turning the entire endeavor TOTALLY WORTHLESS. So what I'm trying to say is: you got a solid framework with great patterns put in place already, developed by a company that is on the tech top 10, and you decide to be all trendy around it? You're pretty much grinding for a promotion you definitely don't deserve, because you're making that framework worse for everybody that you manage.
Using Emacs instead of Vim, occasionally it actually is more productive.
Objective-C and its weird syntax reached success within the iOS world
Slashdot, fix the reply notifications... You won't get away with it...
Did you make your macros Hygenic?
... goto hell.
This has got to be one of the most incoherent piles of meaningless drivel I've ever come across.
1 + 1 is too, that means 1 + 1 = 01 or 10 in binary.
If you aren't right, then you are using another language (that means they are responsible, the authors) and if you are writing in C then you are probably wrong.
It's pretty simple, but the fact is that whores will be whores and guys will turn gay.
Perl
>Reading Comments >= +2
>Ctr+F
>Glob
>0 Results
Come on...
I can't be the only one that uses globals from time to time....
It saves a lot of time to have a private global (within a well defined black box) than to pass pointers around inside that same code...
You just have to make double sure you aren't fucking it up.
$true
Using sqlserver read uncommitted isolation level when you could just as easily use snapshot or some shit. Limits to unimportant displays and low value reports so I don't care if it fucks up every once in a while.. thing is I've never seen it screw up and nobody has ever noticed or complained about it ever.
Stuffing UTF-8 into databases that don't even understand UTF-8. This works as long as you use the right code page, make damn sure character translation is disabled, never truncate data, don't give two shits about proper ordering of non latin characters or resulting output appearing as complete garbage in most query, ETL and reporting tools. Yet I don't give a fuck, gotten away with it for some dozen years without any complaints. The alternatives are a lot of work I don't want to deal with and significantly increase storage and network requirements which can piss off those trying to skirt by on freebee commercial databases or hosting with providers charging by the GB when few care about language support in the first place.
Ignoring various HTML spec constraints... example title must appear in the heading... or fucking what? It works just fine no matter where the hell you stuff it. I'm not going to rewrite or buffer a whole goddamn workflow just so shit like that is spit out in the right "order".
Liking Microsoft shit...You can pry visual studio and editing C code live in debugger without restart from my cold dead hands.
Total complete utter rejection of exceptions... Exceptions are a totally insane way of introducing bugs and hopelessly impossible to check code. The only reason people use them is because it makes life easier for THEM to code early in the lifecycle with no consideration to what comes next...Well fuck that I only care about being able to verify correct operation under all circumstances... You can't design error free or error tolerant subsystems or systematically verify proper operation of jack shit when everything is a black box that can throw whatever the fuck it pleases whenever it pleases. I write exception free exclusively even though some systems the code implements are paradoxically DSLs with exception handling but that is a constrained environment where no such issues are possible.
Total rejection of garbage collected languages. If you follow a few simple rules you will never have memory management issues... if you use garbage collectors well good luck guessing what the GC will or won't do ... running low on memory because of some unintelligible dependency chasing? Micro/macro stuttering to do GC bullshit? No fuck all of that just learn to code. Memory is by far the most cost free item you can possibly ever fuck up... if you can't manage that how the fuck are you going to deal with not fucking up synchronization, connections, transactions, handles and shit... Things which are guaranteed to cause havoc if you just ignore the issues and rely on GC and exceptions.
Not giving a shit about how small throwaway utility programs are written. Have no problems writing complete unintelligible geek code in the most dynamic scripting language chalk full of automatic variables I can get my hands on when maintenance cost is essentially zero.
Strong but conditional dislike of OO*. Great if your writing game engines and some business shit but many things we work have proven to be more of a liability leading to the same tired old inheritance traps. Things avoided by abstaining from the Kool-Aid.
Turn off SELinux entirely.
According to Lennart Pottering, turn off *every single systemd feature* and using tools compatible with old code and other operating systems.
Also according to Lennart Pottering, let user processes continue after the user logs out or gets their shell session disconnected.
Store credentials in plain text, because "you trust the people you work with" and "if they have access to your system, you're lost anyway". Subversion still does this, and 90% of all SSH users do this by keeping their private SSH keys without a passphrase, which is still the default behavior of ssh-keygen.
Do not even bother checking for disk warnings, since more than 1/3 of the time disks fail without warning.
Never apply updates to the operating system, at all.
Use maven, CPAN, nodejs, pip install, or any other tool that builds a random assortment of the latest versions of publicly available components and has no working way to lock down all the dependencies before starting or even to effectively roll them back.
Java, C++, or any "object disorientated" code.
Tail looping.
Never sanitize inputs or checking for error codes.
Timestamp your backups with the timestamp of the backup directory (rsapshot).
Never write checkpoints in batch processing tools.
Was going to be sarcastic and answer "Ruby on Rails", but I'll go with "process per request" instead. That is, the Apache model, or for Rails the model where you keep a pool of instances that only handle one request at a time.
Terrible in terms of scalability, but generally works for small workloads. Plus it largely sidesteps developers having to understand how to write thread-safe code.
goto.
*Takes cover*
0) Counting from zero.
1) Whitespace characters with different meanings.
A guy I work with uses left join for everything when the majority of the time an inner join would be more suitable. Oh well, it still works.
This is my sig, there are many like it but this one is mine
Talking 8085/Z80/6502 assembly days, there were 2 things you just didn't do.
1. Recursion. The relative merits of this have already been dicussed, so I won't belabor it here.
2. Self modifying code. To my knowledge this is still considered a bozo no no, however I found it fast and effecient when resources like memory were still at a premium.
It's definately a bad idea that sometimes worked not only well enough, but better than any other solution available.
People crap on that language and, when I use it I usually violate MVC hard enough that it needs therapy. Yet, damn, I can pound out high quality products in that format like I am a programming firehose. I am talking products that make money and need little to no maintenance for years to come.
I can do python flask stuff that is technically cleaner, I could even do something super hardcore like a C++ we back end but for the easy homerun, PHP it be.
Obviously I am talking about the web.
Another dirty secret is that I do most of my stuff from scratch. Nearly every framework or great IDE extra out there I ignore. The whole storyboards thing in iOS, nope, Java on Android, nope, or just about any proprietary system that tells me how I should do something is a big fat nope. I find with most huge frameworks that I can knock of an almost fully functional prototype in no time at all, but then I start fighting with the framework and can never finish, 90% done and that is it.
By working with the fundamentals and good libraries, I start slow, and finish slow, but finish I do.
If you need templates, implement them generically via a preprocessor but don't use crap like AUTOSAR. Yes, it works. But it takes far longer than if it had been done right. FIBEX files are nice though.
Did it once while implementing a serious e-commerce engine, still in use 13 years later. Tried it a few different ways, propagating errors and user dialogs using java exceptions just turned out to be the best way.
Everything you do has risks and rewards. Bad programming ideas are only bad when you don't understand them. If you are skilled enough to know all the best approaches and fundamentally understand the problems that they are trying to address, then make an informed decision to implement a bad programming idea, I will not fault you for it. That does not mean that I will not question it or seek to understand it at your level.
Clever solutions work. For now. But when they contain a bug they are a major to pain to analyze and fix, and it only gets worse once it is somebody else's clever solution.
Allowing (or forcing) application programmers to do system programming. If your language forces the programmer to reinvent the wheel - he will invariably do it badly. The corollary to this: poor libraries/frameworks/abstractions built by aforementioned programmers then let bad programmers spread even more bad code.
This, by the way, is the source of all zero days.
If you have to do system programming - make sure you have a bona fide systems programmer - preferably who has a thorough understanding of secure programming - on the team; either as a reviewer, or designer.
Given that there aren't that many real system programmers out there - those that are should focus on building tools that keep application developers from shooting themselves in the foot (so they don't have to be there to keep the carnage from happening). In this instance, I am all for gun control. You don't give a child a loaded gun, and you shouldn't give an application programmer one either.
Lodragan Draoidh
The more you explain it, the more I don't understand it. - Mark Twain
I'm forced to support an Excel sheet for mass data entry into a web application. The people using the system can barely understand how files are handled in general, so the concept of "save as CSV, then upload to web" is too complicated. There is a built in VBA macro that extracts the current sheet into a new document, uploads it behind the scenes, then triggers the web app to process it. Luckily, XLSX files are just ZIP files with XML files inside. So the worlds shittiest XML parser is used to handle those documents, since I know it doesn't need to meet even 20% of the full XML spec, just enough to handle one single Excel sheet at a time.
Variations of this system have been in place since Excel 2003 ...
hard coding server names, odbcs, queries, stored procedures of test environment in library scripts to avoid altering the script during dev and deploy and the support due to differences of environment. Just deploy and run!
If something is a private variable that comes with a pair of trivial get/set functions, it is arguably already public, just with lousy syntax. Just make it public.
"But what if we want a less trivial get/set later on, JohannesG, what will you do then, huh?"
Simple. I will move the variable into the private section, add the required get/set functions, and let the compiler tell me where I need to change the code to call them properly. So what if I have to edit 10-20 lines? Because usually that's about the worst of it... And if you know it is potentially going to be much more of course I wouldn't recommend this.
Also, magic numbers. No, I'm _not_ going to declare a constant or enum for every damn possible unnamed value I could send over your MIL1553 or RS232 bus; if your damn manual cannot be bothered to name them, neither will I. Most of these occur exactly one time in the program anyway, and if I have to do any debugging I'll be comparing my code to your manual. I'd like both to speak the same language, and if you chose that language to be hexadecimal, I will happily include those magical hexadecimal numbers directly in my code, screaming QA drones notwithstanding.
Memory is cheap. Sometimes it's just plain faster and simpler to allocate an oversize fixed-size-array than to mess with dynamically allocating and freeing memory.
Fixed size arrays explode if N ever gets above your array size. There are many cases where you should NEVER do this... anything safety-critical or crash-critical or anything which might come under attack. However there are cases where you can assign an acceptable real-world practical limit on N and simply allocate an abundance of memory for it.
- - You can't take something off the Internet! That's like trying to take pee out of a swimming pool.
Seriously, the first time I saw Duff's Device I really thought it was a mistake. It's a do/while intermingled with a case statement. Look it up and be amazed.
VHDL. Worst piece of trash language. It requires someone to write out verbose repetitive lines for one single simple thing, and is overly sensitive about types.
There's a reason why majority of the companies have been moving towards Verilog/SystemVerilog.
What is called "Wasteful algorithms" is not bad programming but another way to present a good old programming practice: "premature optimization is the root of all evil".
I think the main rule is: "It is ok to violate rules as long as you know that you are violating a rule, you know why you are violating it and you know the problems you may face".
It turns out OOP can be a pretty good tool for name-space management in many cases, but it has stunk at domain modelling. Domain modelling is how OO was "sold" to us for roughly the last 2 decades, and this was a fat mistake that turned many prematurely gray.
An example of domain modelling would be a human resources app that models employees, managers, offices, etc. as objects. This mostly flopped.
But OOP works fairly well for making API's to network and system services (and arguably GUI's, but that's another subject).
We were doing it wrong.
Table-ized A.I.
The topic for the article is almost as pointless as, "Which programming language is the best". The answer doesn't get much better than, "It depends". This is all about context. No programming language/technique is definitively 'bad' in and of itself. It's only 'bad' when the solution doesn't suit the context.
Quoting from the article, a "masterful pile of engineering and computer science" isn't appropriate where you only need "one simple input". But a problem that justifies a "masterful pile of engineering and computer science" couldn't be summed up by "one simple input". You end up with thousands of "simple inputs" that are far harder to understand. The whole point of abstraction is to break down complex, overwhelming problems into discrete, comprehensible components. This really matters when problems are so large that only a team of people can deal with them. But it would be a colossal waste of time for problems on the scale of a single spreadsheet macro.
The article would have been better titled, 'Choosing appropriate solutions".
I agree. Just look at Donald Knuth's algorithms and see how "while structured" they are. Well ... they aren't.
I thoroughly understand the need to keep vast wodges of code structured, modular, and (if possible) even while-structured. But when it comes to the core algorithms (numerical or non-numerical) buried deep in library routines, CSC dogmatism should (and usually does) go out of the window.
Open source advocates are especially against this bad idea, but often reinventing the wheel saves time, because it takes time to find the code you want in some open source program, especially if you need to understand it. I know expert level programmers who have all but mastered OpenGL in a day, but few can gain that level in a day, sometimes it takes not so long to write your own OpenGL equivalent ( extreme example :)), but you know what I mean, sometimes just doing it yourself is better for the project.
A guy I know connected the xml-socket datastream of a very large media/music database of a very large global media corporation wth the online service of a very large global telco provider with a sed script he wrote in 30 minutes. They paid him 15000 Euros per month for a few years to mainain it / guarantuee a reaction time of und 60 minutes, not really caring for the details.
Thinking twice about this had me conclude that there probably is no better tool for this job than said sed script. Imagine the hassle and flakyness with some large convoluted Java Appserver setup requiring extra hardware with failovers and stuff.
We suffer more in our imagination than in reality. - Seneca
It even makes sense but I hate it somehow. http://www.nongnu.org/gsequenc... http://www.nongnu.org/gsequenc...
While lambdas are great for some things i had a new guy write a year of his software with lambdas anywhere that could be used. I had to get used to reading code backwards, it was like learning to ride the backwards bicycle.
The worst code can be easy to fix and follow with any naming convention that uses long meaningful variable names.
The best code gets dusty and rewritten if single letter and hard to follow var names are used.
Pick a way and use it, even if its not the latest cool way, follow it.
Did you really just say that the epitome of common sense, the hierarchical filesystem, is a bad idea? If so, spotted the millenial.
Microsoft's OS is really bad software, but seems to work well enough to gain a monopoly.
Windows 10
If it's a stupid idea and it doesn't get the job done, then it's just a stupid idea.
If it's a stupid idea and it gets the job done, then it's a brilliant idea.
Object oriented programing. "Why shoudl I care how it works?" coding at its finest.
Personally, I detest large programming projects. For me, if I need over 1000 lines of code, I am using the wrong language or the wrong framework.
If you are writing a 10-line function, which you can see in a single eyeshot, you can sensibly use single-letter variables and understand what stuff does, just as traditional mathematical notation does. If you are writing a sub 100-line script, again, techniques developed to manage 100,000+ line projects are inappropriate, wasteful, and tend to turn that 100-line script into a 10,000-line behemoth.
When you write something, it should be clear from reading the source what it is meant to do, how it does it, and hopefully why it looks the way it does. It is also helpful if it actually works, but given a preference, I would rather have clarity and succinctness first, since then if it doesn't work, it won't be that hard to fix. On the other hand, if it does work for its intended use, and that use changes slightly, you're stuffed.
So to now answer the question: just about any commercially available software is an example, just about any OS, including Windows, OSX, and any Linux distro is again an example. Stuff that I don't consider 'bad ideas that work' are rare gems. But there are not enough of those rare gems for practical purposes, so I put up with Windows, OSX and GNU/Linux for now.
John_Chalisque
Views allow you to operate on the database as if it were denormalized, without losing the consistency guarantees and other benefits of a properly normalized database.
It's the same concept as STORING datetimes as a number internally, a consistent, monotically increasing number, while DISPLAYING them as strings like "November 6, 2016 1:30 AM". Storing "November 6, 2016 1:30 AM" is crap for any kind of calculation, especially because that string represents two different times an hour apart - there's no way to know whether that comes before or after "November 6, 2016 1:20 AM".
Similarly, views are virtual tables which provide whatever you'd like the user to see, without breaking the underlying data structure.
Work is like "best" - it is meaningless without a rubric.
The question behind the question is therefore what are some measures of goodness that are served by having what a good programmer would call "crap code"?
Good, fast, cheap - pick two. This means that cheap and fast are going to exclude good.
Better is the mortal enemy of good enough. This means that a line is drawn and as soon as the product is over the line, it is shipped. (Microsoft mentality)
Versions of Fast
- Minimum viable product
- No documentation, or maintainability
- political appearance of progress
- quick fix for today with intent to wholly rebuild next week
Versions of Cheap
- Off-shored work done by hacks for pennies on the dollar
- Done by college students in a garage
Malicious hiding
- hiding talent in hacks, or cracks by making it look like a robbery instead of an assassination
- Trojan horses in the allegory sense, not the password catcher. More common in ransom-ware.
Non-malicious hiding
- sharing the brunt of a problem in a public forum without disclosing/revealing underlying IP
Fast/Cheap mix .... instability of the tools
- no documentation
- no reproducibility
- no annotation
- no test cases
- if the build fails try again because it might work next time
Sometimes cheap is about the tools, not the developer.
There is "crazy" or "divine" depending on perspective. (TempleOS)
Indeed, if code is nested 8 levels deep, four or more of those levels should probably be separate functions. The first function might be: .= build_sql(line)
while (line = readline) {
if (notcomment) {
sql
}
}
return sql
The levels of indentation related to building the sql are off in another function, called build_sql().
Human working memory can hold about 8 items at a time, in this case 8 lines of code. Which means you can look at an 8-line function and understand it all at once; you know what those 8 lines are doing. When looking at a 300 line function, you have to scroll up and down parsing parts of it at a time. That greatly increases bugs. Functions no more than 8 lines can normally be seen to be correct - you can fully understand it, without need to scroll up and try to remember how foo affected bar 250 lines ago.
Back in the early 90s I worked at the big cellphone company. We worked on Unix workstations, and I learned a lot of what to do and what not to do. We used an in-house built bug system built to use sccs. I managed the build shell scripts. The only way to get code into the build was to enter a CR (Change Request) and link the source files to it. Then the build would examine all the CRs for a weekly build, check out that code, ftp it to the target platform (tandem), build it. If all went well, 8 hours later you would have a successful build, which I would then write to 9 track tapes, and THEN install it on the target system testing platform.
So the bug system I mentioned used flat readable text files to store all the info. There was a gui front-end but it was kind of slow.
Out of necessity to quickly look things up, I wrote a shell script that would allow you to search and view CRs on the command line. Bad built on top of bad, but it worked pretty well. Other people on my team started using it too.
It worked so well in fact that somewhere around 2006 I was living across the country, having been at a few other companies since then. An old colleague still at my first company got in touch with me, and someone was asking about me and the tool I created. They saw my email in the header of the script, and wanted to get in touch with me to see if I would let them edit it. They were still using it! What I created for myself others found so useful that it was still chugging along doing its job on the command line. I don't know if it made me proud or sad, but it was humorous to me. I haven't heard anything from them since then, but it would be very interesting if they were still using that same process and those shell scripts I created so long ago.
My beliefs do not require that you agree with them.
By the time you figure out how to do what you need to, the requirement has changed. And the language you used, no longer fits the bill.
Thank the language gods for gotos.
I had written this tree-traversal code that I was trying to optimize, because although it was a O(log n) solution, it was slower than the O(n) solution for many of the problem sizes I was dealing with. Unfortunately, I couldn’t just choose one or the other dynamically because the data structures were completely different. Using a pragma, I got the compiler to unroll the loop, and that helped a LOT because there was this array of constants that got nicely integrated into the unrolled loop code. While I was looking at this, I realised that there was this one branch that there was this one if condition where if it was ever executed at all, and it was true, I would bail out, while if it was executed and was false, it would never become true. So what I ended up doing was defining some macros kinda like this:
#define M1() \
if () { } else { goto the corresponding next M2 macro }
M1(0)
M1(1)
#define M2() \
label: \
doesn’t include the if.
M2(1) ...
M2(2)
That just about doubled the performance. It could probably be better. Because of commonalities between the two macro expansions, LLVM thinks it’s clever and rearranges code so that I have a bit of a spaghetti of unconditional jumps. I was also getting some really weird instruction sequences, like:
lea EAX, [expression]
mov EBX, [EAX]
Why not combine those into one instruction? As far as I could tell, this value in EAX was never used for anything else. I also saw this a few times:
mov EAX, EBX
mov ECX, [expression involving 8*EAX]
Why not just us EBX directly?
I thought about reporting this as a bug, but the instant I tried to make an isolated test case, the anomalies disappeared, so what I did was separate this code into its own compilation unit (which I had planned to do anyway, wrapping it in a C++ class). Oddly, even without the code anomalies, the speed wasn’t measurably different. On a modern x86 processor, hardware instruction parallelism can slip lots of extra instruction in basically for free, especially when there are memory accesses going on that might be an L1 miss.
I firmly believe in the axiom: Use XML as a solution, and then you have two problems.
It's astounding how proliferant such a shitty data structure has become.
In-house product integration and automation was a marvel in it's time.
It's legacy, now, is a generation of companies locked-in to one platform, product and age. And a living nightmare to maintain it all.
Being a webapp developer I have to deal a lot with fanboys and con-artists.
If something is "perfect" it's usually because of one of two reasons:
1) Either it's unpopular and nobody uses it, or 2) it's become so popular that everyone is afraid to bad mouth it.
Either way, perfect products are hard to support because nobody discusses issues with them.
Host Application on Windows Server
> when I try to write neat code, I'm always aware that ever single call is a call, so there's the efficiency hit in context switches.
On the topic of efficiency, given the choice, would you rather use up a resource that's worth a penny or a resource that's worth $1,000?
Suppose the function call takes 50ns of CPU time. Suppose we hit that function call a million times. The total cost of a million function calls is about 50 milliseconds. Let's convert that to dollars. Suppose a CPU core costs $350 and lasts 157680000000 milliseconds. So a million function calls cost $0.0000000002.
Your time costs approximately twice your salary (the company pays for your office, your computer, your health insurance ...). Suppose you are cheap, you make $50K / year. That means you cost $100 / hour, or $1.66 / minute.
One minute of your time costs 830,000,000 times as much as a million function calls! If you spend one minute of your time ($1.66) to save that function call ($0.0000000002)
Suppose the function were called a TRILLION times. It still costs 830 times less than spending a minute of your time on it.
The most efficient thing is to save yourself the time. Unless the function is called a QUADRILLION times, it is wasteful to be worrying about it.
You can add Jquery to the list as well. It functions okay unless you need to modify/custom it. It's bad enough, I no longer admit to knowing anything "language" which corresponds with web pages.
PHP is nasty, but not as bad as trying to 'correct' XML by hand. All of the IDEs I played with have a issue with cleaning its own code.
From Round Hole,
Please go look at some old houses and barns. Guess what, the construction is almost all "post and beam"...and guess what, they did it by hammering square pegs into round holes.
Why?
Because it is very hard to drill a square hole. And making round pegs is far more labor intensive than square ones, and wastes a ton of wood. Lasty, friction baby.....that's right. A round peg in a round hole will either slide in and out too easily and not be secure OR it will be so tight that the friction will make it nearly impossible to fit it in. So instead, they hammers a square peg into a round hole. Both the peg and the hole deformed slightly. Allowing for a tightly fitted peg to lock the post and beam together.
The last several years of my career - which was as an engineer that did a lot of programming, not a programmer...but the IT department was so hard to get hold of, or get results from, I ended up doing a lot of "favours" around the office -- I did a bunch of web pages with perl scripts.
I never got into Javascript or even much DHTML, so these looked like 1993 web pages. They had a few simple forms with a couple of text boxes, a radio button set, etc. You could get customized reports with them that IT just didn't have time for...and I could customize in a new feature in an hour or two. So they grew like coral over a few years, and we ended up with several of them before the requests wound down.
IT was not happy...not because I'd used poor programming practice. (I have a CompSci degree too, I know how to comment and write clear code.)
No, IT thought it was awful because of the 1990's Perl/CGI-gateway architecture; only Microsoft tools should be allowed, this was unmaintainable, etc. ("Unmaintainable" continued after a junior engineer took over maintenance when IT wouldn't. He had the code figured out in a few weeks.)
I guess my point is you need to put "Bad" in quotes, because it's always an opinion...and lots of people mistake "bad" for "not the current fad".
The entire reason this worked is that these were *small* problems; IT could have done them easily, but each report only served a few people and IT was consumed with Big Systems that served everybody. That's also why there were just a few of them needed, it was a small "market". So I guess another point is that you don't always have to use the giant Official Corporate Development Environment Hammer to hit every nail. Those are chosen to be able to handle Big Problems, but the overall bureaucracy can be too heavy to nimbly solve small ones. Be open to small, simple, script-sized solutions. IT people constantly call those "Bad", usually with dire warnings that they will grow and become spaghetti-code monsters that will suck up all your money.
With respect, what the F do they know? They only get called in for those monsters. They may be unaware there are twenty times as many out there that did NOT grow into monsters and the small solution was just right and ran for a decade. So the next time you're pretty sure you just have a Small Problem, tell IT to stuff it and solve it yourself.
Sometimes, when my software stops for no apparent reason once every few weeks/months, it takes too much to figure out what's wrong with it, so I just re-use a piece of software that checks if it's on or off and restarts if needed. Sort of automatic recovery in windows services.
This gem was posted on reddit recently :
Operator <- : http://www.atnnn.com/p/operato...
Reddit thread : https://www.reddit.com/r/cpp/c...
it may be ugly to the purists but it gets the job done
When you can't be arsed to write a config file parser and you decide to just use a blob of serialised data as your config, you're making a mess for everyone who uses your software. That said, lots of people seem to be doing it. My pet gripe at the moment is RabbitMQ, but there are plenty of others (sendmail definitely, nginx maybe).
Programming.
> Views only help on the output side, not the input side.
Not normally true if your base tables are in normal form.
If your base tables are *not* normalized, updates (through views or otherwise) are a crapshoot. If the base tables are normalized, you can update them through a de-normalizing view.
Aggregate views (reports) are of course not updateable. Updating an aggregate would cause your totals to no longer match your detail records. That's a good thing.
GOTO, I LOVE the goto command. No messy loops, just jump straight to the line you need. But that's considered "bad programming" Pssshhh!
I've seen polling succeed in places where complicated registration processes maintain a lot of failed connections and crash.
Seems to work good when only a few clients are involved.
This has mostly been with socket programming, but the web socket stuff is getting so easy to set up now it might work better than polling.
Amen! Productivity (work-related) application programming (CRUD) using HTML/DOM/JS is a f8cking nightmare.
Part of the problem is that each browser brand/version combo can potentially render things differently such that you have to test on say 30+ combo's of browsers and devices to cover all bases, AND future versions may STILL break it after all those 30+ tests. My hair is turning Bernie Sanders shades over that crazy shit (and falling out like his). It makes the DLL-hell of the 90's feel better in comparison. Now we have render-hell.
Possible solutions include bringing back WYSIWYG and/or vector coordinates, OR doing the "auto-flow" rendering on the server and making the browser be a dumb coordinate-based vector plotter. That way you are dealing with only one renderer instead of 30+.
Another idea is to put X Window engines on browsers, but I'm skeptical of the input box response. Input boxes should (optionally) buffer on the client.
Other ideas welcomed.
Sure, you if you put a lot of bloated margins around everything you can make stuff "shift proof" in the web stack; but it looks ugly, wastes space, and is often not what the customers want.
Table-ized A.I.
From the original unscaleable unsecured NetBIOS implementation all the way to the currently supported kerberized sorta-NetBEUI over IP, Microsoft's networking stacks have always been *vastly* inefficient - both on the wire and in the node. It's a grotesquely bloated implementation of a horrific design.
However, Microsoft has *always* (well, since Win3.11 wolverine, anyway) provided good support and consistent implementation, keeping their security patches and OS upgrades from breaking connectivity pretty reliably. This contrasted so strongly with 3rd party stacks like Novell, Banyan, &etc. that most of the 3rd parties have gone out of business! It just wasn't worth the hassle of having Microsoft updates constantly break every PC's network connectivity and having to schlep around floppies of 3rd party network stack patches, so we all settled for the really bad MS networking stack that requires far less maintenance, and made up the difference with hardware.
I think the following could be considered a thunk hack:
This was an IBM 1130, where integers were 16 bits, but Extended Precision Floats had a 32 bit significand. I wanted to be able to float 32 bit integers. I wrote an EFLOAT(J) function in Assembler. It returned an extended precision FLOAT, but totally ignored the input parameter, except for stepping past its address when returning. Actual usage was, E=EFLOAT(K*L), where E is an extended precision float, and both K and L are integers. I knew that integer multiplication actually produced a 32 bit result spread over two particular registers. EFLOAT floated whatever was in those registers, still lying around from the function call. It totally produced the wrong result if you actually called it with just an integer variable as input.
Would it have been less obtuse to write the function as taking two integers and multiply them inside the function, EMFLOAT(J,K)? Sure, but less fun.
I had to write an interface between 2 applications on an AS/400. The apps were surprisingly similar in certain key ways, and crucially in the way they defined Companies (these were explicitly multi-company systems).
However there was a problem. Company 099 in System A could map to Co. 099 in System B, but in Sys B it was also in a different set of libraries. Uh-oh. I raised the issue in design and was directed (against my wishes) to hard-code the mapping.
The crazy thing was, it worked! It was nasty, inelegant, hard-coded wrongness. It worked though because all the structures I mapped, were totally static in the real world. It could all have been changed theoretically, but in practice it never was. No one ever even asked to do so. Turned out to be one of the highlights of my career, an interface that was in the most sensitive part of the system you could imagine, and it never failed. Ran perfectly for 7 years.
sometimes it just has to be done...
First, if you have millions of jpegs (to use your example) in a single directory, and you actually have a good reason (besides laziness) to keep them all in that single directory, then you probably also have a plan to deal with them efficiently.
Second is the issue of trust. I simply trust myself and my organizational skills more than I trust you or your software. I would never rely on some arbitrary piece of software to eliminate the "burden" of organization. Perhaps it's a reasonable approach for the computer illiterate, but for me it's yet another solution looking for a problem. What's next, the computer wiping your ass?
Everyone knows global variables are bad, but when you need to ship an app soon and would have to modify a dozen classes and methods to transmit one tiny piece of information from the top level of an app all of the way down to the bottom (or vice versa), a global variable works nicely.
This site is social engineering.
SIGINT/HUMINT
The prototypical example comes from the 1991 Usenet post The Rise of Worse is Better. The basic idea being that its better to push out something simple and get it into user hands than to always be trying to do the Right Thing. Sort of the larval stage of the concept iterative design (but without any formal planned iterations).
I and just about every designer of Common Lisp and CLOS has had extreme exposure to the MIT/Stanford style of design. The essence of this style can be captured by the phrase ``the right thing.'' To such a designer it is important to get all of the following characteristics right:
I believe most people would agree that these are good characteristics. I will call the use of this philosophy of design the ``MIT approach.'' Common Lisp (with CLOS) and Scheme represent the MIT approach to design and implementation.
The worse-is-better philosophy is only slightly different:
Early Unix and C are examples of the use of this school of design, and I will call the use of this design strategy the ``New Jersey approach.'' I have intentionally caricatured the worse-is-better philosophy to convince you that it is obviously a bad philosophy and that the New Jersey approach is a bad approach.
However, I believe that worse-is-better, even in its strawman form, has better survival characteristics than the-right-thing, and that the New Jersey approach when used for software is a better approach than the MIT approach.
Let me start out by retelling a story that shows that the MIT/New-Jersey distinction is valid and that proponents of each philosophy actually believe their philosophy is better.
Two famous people, one from MIT and another from Berkeley (but working on Unix) once met to discuss operating system issues. The person from MIT was knowledgeable about ITS (the MIT AI Lab operating system) and had been reading the Unix sources. He was interested in how Unix solved the PC loser-ing problem. The PC loser-ing problem occurs when a user program invokes a system routine to perform a lengthy operation that might have significant state, such as IO buffers. If an interrupt occurs during the operation, the state of the user program must be saved. Because the invocation of the system rou
how often do you really need to customize jQuery? Seems like if you're at that point you're either doing something wrong or shouldn't be using it in the first place?
Huge, but actually quite predictable.
With just the values of 2 variables you know exactly where your program should be executing/where to throw in a breakpoint.
I've used goto in C against better judgement when implementing a key derivation algorithm from an ANSI standard. The algorithm was described using some horrible spaghetti pseudo code with goto jumps between code sections which made it impossible to break it up in neat functions. I ended up writing it all as one big function with the goto's and everything. It works and is still used 10 years later, but I get to explain myself every time that function goes through a code review.
.
Once I had the standard application pages so that it all groked correctly, and built my temporary DB on the other partition of the Mainframe, it took me only about 6 hours to write the program that DP was telling us was impossible to do. You should have seen the face of my managers face when I walked into his office carrying a very thick ream of printouts with the all the answers he needed that day. Once the DP manger got finished being chewed out by the president of the company, that same program, utilizing the Big-Iron mainframe and with a direct connection to the actual database, it took over 6 man-months to write the same in COBOL. DP offered me a job writing Cobol, and I said no, turned professional a couple of months later and never looked back. I decided solving problems was more fun than pushing parts through a factory.
I wouldn't know the full details of which RDMS supports what types of updates, but they've always worked for me, when it makes sense for them to work. (Ie, obviously you don't update a sum.)
But I haven't tried too many different updates of user-friendly views, because I generally design my systems where updates / insertions aren't normally done manually by ad-hoc queries. People can retrieve data with ad hoc queries if they choose, no harm in that. For inserts and updates, I want those controlled by the software anyway, with all the proper validation.
Since the inserts are done by software, there's no problem writing the software to use the base tables. In fact, if you have even a general concept of objects in mind when writing the software (not necessarily full OOP), tables which reflect your objects may be easier than human-friendly views anyway.
So anyway, yeah I haven't updated THAT many views, and I'm glad I haven't.
You are of course welcome to write rambling 800 procedures if you choose to do so. You won't while working for *me*, but in your software, do what you want.
In the kernel, we use the 24x80 rule. Lines no longer than 80 characters, and functions, from kerneldoc to ending brace, should normally be less than 24 lines, shorter if they are more complex. That leaves 20 lines for the function body - if the function isn't particularly complex. Complex stuff needs to be shorter. That rule works for us. We're happy, our 85 million users are happy. If you have 85 million happy users, keep doing what you're doing.
Nothing worth reading.
BOTH are a matter of wrong-tool-for-the-job.
ColdFusion (CF) was originally intended for HTML templating to make it easier for graphics designers and HTML-only coders to code for RDBMS-supplied content without having to bother the app dev for minor changes. It worked so well that CF started to be used for more general or complicated programming, and that's where you found ugly limits*.
Similarly, JavaScript was originally designed as a light-duty glue language to handle browser events not built into the HTML standard(s). It worked well enough that people started using it as a systems language to implement entire GUI engines, and found ugly limits (which I rant about in detail elsewhere on this story).
The same pattern played out in JS and CF:
1. A tool is designed for a niche
2. It's highly successful in its niche
3. Popularity causes uses outside of original goal
4. People complain about the ill fit, summarily blaming the tool
5. Tablizer chews them out for painting with a wide brush
A similar thing happened with VB classic. It was intended for smallish internal applications, but people tried to build enterprise-sized or packaged software with it, and it choked under the weight and got a bad general reputation.
A similar thing also happened with IBM's RPG (Report Program Generator). It was intended to simplify the generation of reports. It was successful enough that others started using it for general application programming, and vendors wrote entire applications in it. Many programmers complained about it and bad-mouthed it in general.
* CF is still well-suited for the original goal. In additional to built-in CF XML tags for populating HTML with data, one can build custom XML tags so that HTML designers/coders can use XML for common tasks for a shop instead of having to learn a "regular" programming language. One can argue they "should" learn regular languages, but if they won't or can't, CF is a nice tool for them. It has full subroutines now, and a feature set comparable to ASP classic. With some exceptions, one can even code in a JavaScript-like variant of it if you don't like XML.
Table-ized A.I.
I have seen this done many times, bad code, so just throw more CPU's, RAM, IOPS to fix it. Often cheaper and easier than getting the real problem fixed and it works - to a point when you can't add any more resources.
Sorry, I still don't see a strong relationship. An esoteric convoluted tool (ECT) could make one a lot of money because it's often hard to find experienced and skilled experts such that an org relying on an ECT system that needs maintenance would be willing to pay a premium for it.
There are well-paid Java coders and poorly paid Java coders; there are well-paid PHP coders and poorly paid PHP coders.
The supply versus demand versus difficulty relationship is complex and changes over time, and often driven by tech fads. I haven't seen any clear-cut patterns other than the rise and fall of techie supply can vary differently than a rise and fall of demand; and that if you are on the right boat at the right time, you can make good bucks.
Table-ized A.I.
Re (a): Show us one! Show us a practical and realistic example app. Avoid those dealing biology, physics, or geometry because those are not representative domains. Most business objects are defined by laws or market forces, and subject to a lot of changes. Physics stays the same, but intellectual property and laws do not.
Maybe a college system that tracks students, teachers, classes, grades, etc. Then show us how OO makes it better in terms of fewer bugs, maintainability, etc. Invite readers to run some change scenarios on it.
Re (b): For the sake of argument*, let's say some of us are just inherently too dumb to get OOP (at least OOP domain modeling). Should we just exit software development? But what if we are perfectly productive using other paradigms/techniques? Just because we suck at paradigm X doesn't mean we also suck at paradigm Y.
And there are other skills involved in software engineering, such as people skills, writing skills, UI design, other IT skills such as server admin, and domain knowledge (knowing the customer's industry).
We may be good at these others but suck at OO. That's not reason enough to toss us because there are other important factors the org that hires us is weighing.
* I personally believe it's either a bunch of hooey, or a personal choice being mistaken for a universe truth.
Table-ized A.I.
For what it's worth, per "OOP" here's my preferred definition of "object": a map or map-like data structure that can hold both attributes and behavior (or pointers to behavior). These units of behavior are typically called "methods". And objects facilitate easy or automatic referencing a parent object(s) for attributes or behavior not explicitly defined in a given map.
("Classes" are a language-specific variation or restraint on the concept.)
In short, a glorified map data structure (AKA "dictionary").
Table-ized A.I.
Ironically, Java lambda's are often used to work around its poor OOP model. In a good OOP language, it would be easy to add an "On Click" method to a given GUI widget. Seems like a straight-forward and common feature, but Java provides no easy to let the listener know about such a method, such that one has to talk to a GUI listener directly instead via lambda's. (Maybe there's a way around this, nobody I know has solved it yet, without side-effects.)
Table-ized A.I.
Indeed. And well-factored is not necessarily the same as "useful". I've made what I thought was "beautifully factored code" and patted myself on the back thinking how clever am I.
THEN the domain requirements changed, and went against the grain of my factoring, creating a mess. Parsimony can show you how to factor an existing abstraction, but says nothing about the future.
The most future-proof abstractions in my observation are bunches of smaller abstractions that can be discarded as needed: a set of little functions or utilities that can be glued together as needed or ignored as needed.
"Big umbrella" integrated frameworks are a disaster waiting to happen because they are too hard to unwind: it's all an interconnected ball of yarn. There is more annoying glue-work between the abstractions when using smaller abstractions, but they handle future changes better. It's better to live with more glue. Break big abstractions into parts that can be used independently.
Table-ized A.I.