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
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.
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.
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.
I'll take that and raise you VB6... or VB in general, old and new.
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.
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
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.
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"
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.
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 . . .
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).
Magic numbers save tons of time. You get to working code quickly to verify your algorithm. They nev
>Segmentation Fault
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.
I do that fairly often, but like:
case 1: return blah;
case 2: return blah * 2;
default: throw up;
Putting two statements on one line really is a bad idea.
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.
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...
Recursion is not a bad idea. The problem is that it relies on a small memory space that was not designed for that purpose initially (or you have to customize it)
Slashdot, fix the reply notifications... You won't get away with it...
It (may) work.
ftfy
Slashdot, fix the reply notifications... You won't get away with it...
Don't blame devs developing on Windows. They usually don't have a choice due to economic constraints.
Slashdot, fix the reply notifications... You won't get away with it...
Did you make your macros Hygenic?
you should use recursion if you need to use recursion. Conversely, if you need to use recursion, you should use recursion.
rewriting history since 2109
Perl
Works when the boss says it's too cold in the server room.
It was a bit loopy.
Agreed, I once worked on a project with a global array named 'aLocalArray'. It would have been better if they had just named it 'Ass'.
John McAfee 'It was like that time I hired that Bangkok prostitute; to do my taxes, while I fucked my accountant'
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.
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
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.
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 ...
It usually is a bad idea, but it depends on the case.
In this case I don't see the need to break down on separate lines. But otherwise I agree that breaking down to separate lines is good.
switch ( something )
{
case 1: { a=4; break; }
case 2: { a=5; break; }
case 3: { a=0; break; }
default: { a=1; break; }
}
If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
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.
You consider all of these 'bad ideas that do work'? Or merely 'bad ideas and you fail at reading comprehension'?
Also works when a 23 year-old "expert" from one of the big consulting firms reports to the CIO that the servers are underutillised.
My reply was "certainly, what level of utilisation would you like?" but the grin on my face gave it away. It was then followed by a laymans explanation of utilisation vs. response times. And a decision that the consultancy wasn't in the company's best interests.
politicians are like babies' nappies: they should both be changed regularly and for the same reasons
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.
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.
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.
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...
Yes. So much this.
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.
Also works when a 23 year-old "expert" from one of the big consulting firms reports to the CIO that the servers are underutillised.
My reply was "certainly, what level of utilisation would you like?" but the grin on my face gave it away. It was then followed by a laymans explanation of utilisation vs. response times. And a decision that the consultancy wasn't in the company's best interests.
You left money on the table with that.
I don't know the context...how many other people were working alongside this guy, or how representative he was of the team (if there was one) that was there. But if he worked for the consultancy I work for, we'd have wanted to know about this. You should have raised this (along with what must have been several other curious ideas from the guy) to the account manager/account executive/throat to choke (the technical term) for your company. I'm pretty sure that the guy's going to get pushed out an airlock sooner or later, but you could have helped hasten the process.
Remember: it's stupid people - not stupid companies - that come up with stupid ideas. Smart companies want to know who the stupid people are so they can remediate the problem, while stupid companies are nothing more than companies where the stupid people outnumber the smart ones and have taken over. Either way, if you assume the company isn't stupid and act accordingly, you'll get better results. Even if that means finding out that your assumption is incorrect...at least then you know, rather than assume, that the company is stupid.
For your security, this post has been encrypted with ROT-13, twice.
Depends on the utilization patterns.
Heavy I/O utilization will give you a bad time. As a counter-point, overprovisioning RAM relative to your working set will cut back on some of the I/O--a lot, if you're not on a write-heavy workload or a database. Correct RAM provisioning has to include the working set (application memory) and page cache (which is working set represented on disk, rather than persistently loaded into memory by the application).
PU utilization at 90% during peak is fine, if your applications can handle it. A PHP or C# application that can service 5,000 requests per second only takes, on average, 1/5000th of a second to fully-service a request; if it's designed to queue and thread in some sane way, then it shouldn't stall later requests because an earlier request is waiting for something. Its ability to handle 5,000 requests per second includes all that overhead: you can't automatically scale the HW requirements to service 100 RPS and claim now it does 5,000.
An nginx server at 90% utilization typically operates just fine, because nginx (as a reverse proxy, caching proxy, or static file web server) *does* serialize sanely. It provides one worker per CPU (configurable), and passes requests to workers under the least load. Each worker serializes requests--they service one request at a time--and will basically put a waiting request on hold and immediately start servicing a different request. If a worker is waiting with no request to service, it can take a new request--even if it has 37 requests all waiting for something (I/O, a back-end proxy, an application).
Writing an application to handle parallel requests with that kind of efficiency is *hard*. It's not impossible, and some applications handle it well; others do in fact increase latency significantly with utilization.
Latency will, of course, always increase when utilization exceeds unity. Using more than 100% of all CPUs means something has to wait.
Support my political activism on Patreon.
You think PHP is crap? Try M$'s half ass'd ripoff of it it's called ASP
Build a Man a Fire, and He'll Be Warm for a Day. Set a Man on Fire, and He'll Be Warm for the Rest of His Life.
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.
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.
It doesn matter. When you run a server room, and a consultancy _firm_ makes that recommendation, it's not your business to do their HR work for them.
A consulting firm that allows this kind of shit is a liability for the health of your systems, and a waste of resources. You need to get rid of them, and put a higher bar if any other company wants your money or attention. That's the safest bet.
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.
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.
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.
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.
I'd put that in its own function, and write it:
case 1: return 4; ...
case 2: return 5;
1) Only one statement per line,
2) The function can be named to make the code more readable in lieu of a comment explaining the switch..
Can I see you in my office please? :p
Oh, how clever you are!
Popisms.com - Connecting pop culture
This gem was posted on reddit recently :
Operator <- : http://www.atnnn.com/p/operato...
Reddit thread : https://www.reddit.com/r/cpp/c...
Is that you, Accenture?
All those moments will be lost in time, like tears in rain.
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).
> 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.
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.
As a matter of fact, "setting a high bar" was my euphemistic way of saying "do not accept them"
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.
Who said anything about all your JPEG files being in the same directory? Maybe you only have a dozen of them in your whole volume, but if you don't know what folders they are in, you might have to search through 50,000 folders and 10 million other files to find them. Even if you originally knew where you created them, some person or application can move them or rename any folder in its path. Also who said anything about the system doing all the 'organizing' for you? You are still the one who puts on any tags that you want or makes each object a member of whatever groups you want. My system simply gives you better tools for doing that rather than forcing you to put a file in some folder somewhere as a means of classification.
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
It was then followed by a laymans explanation of utilisation vs. response times. And a decision that the consultancy wasn't in the company's best interests.
That worked? Impressive Jedi skills you have
It is unwise to ascribe motive
We have some VB6 apps and they are quickly becoming impossible to maintain since the development environment is no longer supported and getting it to run on modern hardware with modern OSes, especially in virtual machines, is becoming difficult. VB.net however is still very much alive and very usable.
Much better than .XLS files as Program I/O.
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.
If you use short variable names for loop variables and stuff, you can code faster because you type quicker.
Back in college, I had to rename i,j,k,l as indx,jndx,kndx,lndx just to keep the TAs off my back. Single char variable names were FORBIDDEN!! but they never had a good reason for ruining the readability of the code when a quick comment at most would serve to describe which index variable was which.
You might notice that Mathematics texts never use long variable names, and COBOL always does? Nuff said.
Also globals aren't bad, and public variables aren't bad.
Of course they are bad. Necessary sometimes, but bad. So write yourself a comment as to why you are using it, and go on, and let someone else remove it after you have left the company, if they have nothing else to do with their lives. Especially useful for tracking internal conditions in functions when you are debugging and don't want to bother stepping through them.
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.
I dipped my dick into that and it fell off. It was like they took the worst of VB (good in its own way) and the worst from PHP and then somehow sold it to people who somehow became convinced that because it was MS that it was the one true way to make dynamic web sites.
C# is M$ clone of Java and MVC was created by Xerox/Smalltalk in the 70's
Build a Man a Fire, and He'll Be Warm for a Day. Set a Man on Fire, and He'll Be Warm for the Rest of His Life.
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.
Sorry, I'm an old bearded unix guy. I've even worked in the storage industry on file systems. My experience doesn't automatically make anything I say correct, but you may want to take me seriously if I point something and say "you should think harder and not make assumptions about this design".
“Common sense is not so common.” — Voltaire
That may convince the management to get us better CPUs, but we'd be still short on RAM.
I suggest 10 GOSUB 10
45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B2
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.