views:

1442

answers:

19

Have you ever restricted yourself to using a subset of language features, and more importantly, why?

I'm curious to find out who choose to use only certain language features and avoid others in order to win big in areas such as, but not limited to, memory usage, execution speed or plain old readability and maintainability. And by doing so did it yield the expected results or did it perhaps just hamper some other aspect of producing software. Are there any cautionary tales or wild success stories out there worth sharing regarding this subject?

+3  A: 

you certainly do that when you code c/c++ code to work both on linux and windows - so you restrict yourself to ANSI c/c++, so I guess multiplatform support is one of the reasons.

other reasons - if you want maximum compatibility with wide spread software/os (like winXP, IE 6.0 ) - then you target your software to those apps/os (like dot net framework 2.0 and not 3.5 and Ie 6 and not ie.8) - to have better compatibility with old uses.

same goes to old hardware compatibility / old graphics device compatibility ect...

Dani
ANSI C and C++ are not subsets - vendor supplied extensions are supersets.
anon
This is another way to look at it.. but you are right.
Dani
+27  A: 

Douglas Crockford's book Javascript: The Good Parts is a prime example of this. He lists 'features' in javascript that should be avoided and provides alternatives that use the 'good parts' of the language.

A few of the bad parts are:

  • eval
    slower, harder to read, dangerously insecure

  • ==
    confusing and ambiguous with differently typed operands

  • with
    unpredictable results

Brian Ramsay
Thanks Brian. Have you or your team applied these rules specifically? And if so has it resulted in anything awkward or interesting to tell?
Jonathon Watney
+6  A: 

I avoid GOTO which in some circles is considered harmful.

Sam Meldrum
extremely http://xkcd.com/292/
Amarghosh
Depends on the language. In assembly you are almost required to use a goto.
Brad Gilbert
You are not only "almost required" to use them. A goto is the direct form of saying "do a static or conditional branch". A CPU has no other control flow.But I would not call that GOTO anyway, because assembly is just a very thin layer above writing instructions in HEX where there is no syntax at all.
Axel Gneiting
Indeed. I've always thought of that as a JUMP instruction or a BRANCH instruction http://en.wikipedia.org/wiki/Branch_(computer_science)
Sam Meldrum
+11  A: 

One case is when you're writing a compiler of a new language in itself. You can:

  • Use another language to write a simple compiler for a subset of the new language.
  • Use that subset of the new language to write the compiler for the complete version of itself.
Mehrdad Afshari
+3  A: 

It makes sense to not use features your co-developers do not understand. In c++ that goes for most of the language :), but c# also has interesting constructs. Older languages like Delphi might still contain goto. I tend to avoid all templates and XML, as I've found them impossible to DRY

Stephan Eggermont
+1. With some of the co-developers I've had to work with, this has proved to be a challenge. Can you program using only brackets, =, + and - ? :-)
Bob Moore
Depends whether that "? :" is the ternary operator.
Steve Jessop
Honestly, I have mixed feelings about this. If your fellow developers do not have a good understanding of the language then they really need to fix that. Of course, this doesn't mean you should go out of your way to make very contorting logic but if we're just talking about the use of language constructs then I tend to disagree. Some languages have constructs that probably shouldn't be used (i.e. Javascript) but this is a different issue. As well, C# actually has the goto keyword. I agree with you about the XML stuff though.
BobbyShaftoe
Yep, it's not ideal, just pragmatic. I find most development organisations just use a subset of the language constructs. Introducing too many new things at once just creates chaos.
Stephan Eggermont
@Bob Moore: try coding in *a language that shall not be named* (hint:starts with brain)
RCIX
Sorry, but what's "DRY"? (I'm not up on my TLA's here)
Andrew Shepherd
Don't Repeat Yourself
Stephan Eggermont
Basic doesn't start with brain...
Stephan Eggermont
+6  A: 

Although PHP was originally a template language, it has grown into a full-fledged OO programming language. For this reason, some say that it is no longer suitable to use as a template language.

Really, though, it's just a matter of discipline. When creating HTML/PHP templates, I restrict myself to the simplest subset possible: conditions and loops and no business logic whatsoever. No object instantiation. No function definitions. More complex logic is separated into other files.

Lucas Oman
On the subject of PHP, many developers avoid some PHP features (e.g. `register_globals`) as they are considered to cause security risks.
MarkJ
@MarkJ True, although that feature is deprecated, along with other security threats, like magic quotes (ugh!).
Lucas Oman
I avoid all PHP features.
billpg
This is actually a very good example of where featured of the language should be avoided to obtain good results.
Jeff Davis
+11  A: 

Yes, all the time.

Because I use Perl, and most people agree that many of our languages features are best not used unless you really need to and you know what you are doing. For example, symbolic references are supported, but you shouldn't use them. goto exists, but you shouldn't use it. You can re-use variable labels as different types, e.g. $var, @var, %var, but you shouldn't do that, either. You can not use strict to have undeclared variables become symbol table entries automatically, but you really shouldn't do that.

The main reason is that many such features have consequences both obvious and esoteric that can introduce subtle and difficult-to-debug errors into your program if used carelessly. Perl makes lots of things possible and it can be attractive to use certain unusual language features to save a few minutes of coding. There are of course times when esoteric features are handy, and it's great that they are there for you to take advantage of in Perl, as opposed to being absent entirely. But it takes experience to know when that savings is worthwhile, because the vast majority of the time you are just creating a maintenance nightmare for yourself and others down the road.

I am fond of saying TMTOWTDI, BMOTWAW; There's more than one way to do it, but most of those ways are wrong.

It's perfectly possible to create large, literate, maintainable Perl applications. And a good part of doing so is restricting yourself to a subset of language features.

Adam Bellaire
There are legitimate reasons for using goto in Perl -- I almost always make use of it if I'm using AUTOLOAD. (make an anonymous subroutine, insert it into the symbol table, then `goto` it, so if someone looks at `caller`, they see the right function, not AUTOLOAD)
Joe
@Joe: Absolutely, that would fall under the *"unless you really need to and you know what you are doing"* exception mentioned in the second sentence. ;)
Adam Bellaire
My attitude is TSBOWWTDI.
anon
@Neil: There should be only worthy ways to do it? :)
Adam Bellaire
@Adam That was of course a f*ckup on my part. But good catch on yours!
anon
You can also use `goto` for improving tail call recursion. You could also use Sub::Call::Recur for that though.
Brad Gilbert
A: 

Obviously, if features are deprecated, it's a good idea to avoid them, even if they're technically available.

But also, if you're going to be distributing interpreted scripts to run on a mix of machines, I'll often avoid brand new features so I don't force people to upgrade PHP / Perl / whatever just to be able to run it.

Joe
I've done just that recently: I was writing some Python code and limited myself to a slightly less pleasant built-in module rather than using an external library because, well, it means one less apt-get...
Tom Morris
+14  A: 

Most people program subconciously in an informal subset of the their language of choice that they are comfortable with. For example, my first reaction on being presented with a C++ vector that needs iterating over is to reach for a for-loop, rather than write a predicate and use a standard library algorithm. Possibly a failing on my part, but at least I know the algorithm is there if I really need it.

The last time I can remember conciously writing in a subset language was back in the 80s when most of my target platforms supported FORTRAN 77, but one didn't properly, so I had to write in a FORTRAN 77/FORTRAN IV hybrid. It was a pain - things have got a lot better in recent years, thanks mostly to the FOSS movement.

anon
Good answer. I think we all do this sort of filtering all the time, whether we're aware of it or not.
Bill the Lizard
Wow, what you had to do with FORTRAN definitely sounds like a pain. Was there particular pain points that you could elaborate on? I'd be interested to hear. :)
Jonathon Watney
+1  A: 

In many cases, you do that unconsciously - you use the subset you know and leave out the unknown features. In other cases, there is more than one way to do it - and you choose to stick to one way all the time, because it makes a program easier to read when it uses less language features. (Especially when "the other way" has no particular advantage - e.g. it's just here to please people coming from a different language)

ammoQ
+3  A: 

Plenty of times. Main reason for me is cross-platform compatibility. Examples:

1) (ages ago) templates were struck out from my company's coding standard as they were too non-standard across the range of compilers we had to support

2) use of exceptions/rtti for c++ - a no-no if you're targetting an embedded platform as well as desktop ones (disclaimer - haven't done any of this in years, so maybe it's more acceptable now though I doubt it)

3) .NET remoting if you're writing an app for .NET desktop and for WinCE - major headache right now :-(

Kev
+1  A: 

Yes.

C++ is such a large, complex language, it is hard to hire a team that can use every feature in its full complexity. I write style guidelines that point engineers to use certain features and avoid others. It's distressing to have engineers stuck on a bug, and have them tell you they never did know what a certain construct meant. Bad engineer? Maybe, but we have to work in reality.

As people have mentioned, languages like Javascript have some features that can get you in trouble, so it's best to avoid them.

Both of these, and other mature languages like PHP and Ruby, have features from many different paradigms. To use them effectively, you don't necessarily avoid certain features, but reach an agreement on how you are going to use the vast set of tools you have available.

I feel a little differently about Java. It is a much simpler language and I think it is realistic to expect engineers to know the entire language. You do sometimes avoid certain features for backward compatibility, but otherwise I want engineers to know and use all of Java.

ndp
Most people don't really understand Generics in Java, and many don't use it much in their own code except for the typical List<String> blah = ... I would disagree with calling it a simple language (there's other stuff I could point to, like can you write a truly serializable class without having to look it up?)
wds
I just said that Java is simpler than the other languages (not simple). I also think that the culture around Java sets the expectation that you should be able to understand the whole language (or learn it), moreso than other languages. Yes, writing generics is tricky and requires a google or two, but using them is a core skill.
ndp
+8  A: 

In .NET, we have an app that MUST run on Windows 98, so we are limited to the 2.0 framework, since newer versions don't run on this OS.. That's just sad. Can't use LINQ, Extensions Methods and stuff.

Pedro
This is a very good example, when a language change relies on a runtime change as well this sort of thing happens.I would add that certain features do not work in the .Net Micro Framework for example, so if you are trying to write code for both you must use a limited subset
ShuggyCoUk
You can actually use extension methods in .NET 2.0 (if you compile using the 3.5 compiler), see http://www.danielmoth.com/Blog/2007/05/using-extension-methods-in-fx-20.html
Kieran Benton
Some of those features are compile-time only, so you can still use them. For instance I use VS 2008 but target .NET 2.0. I can use extension methods and LINQ-to-objects via http://www.albahari.com/nutshell/linqbridge.aspx.
Matt Warren
You can use extension methods and LINQ in the .Net Micro Framework... keep in-mind is't not very pretty becasue you don't have generics... but it does work. (And I have the code to prove it :)
Matthew Whited
+2  A: 

Did not use some .NET features in a portal project which would have issues when running in partially trusted environments because we had to make sure that clients could deploy the solution on servers with assemblies having weak trust policies.

The thing that hurt most was no reflection could be used!

Gergely Orosz
Were there any situations where using reflection would have really helped? Or did you not really need it?
Jonathon Watney
Yes, we had and extendable module plugin system which went through all dlls in the binary folder and collected the public classes marked with an attribute - used reflection to do so. We needed a declarative solution instead of this approach.
Gergely Orosz
Aw, bummer. I can relate to that but in the other direction. I recently replaced some mundane XML config files with some code using reflection to configure things via convention. It would be a total drag going back. ;)
Jonathon Watney
+1  A: 

I plan to be in the upcoming weeks as I port Lua over to the DLR.

RCIX
A: 

Lotus IBM introduced the getAllEntriesByKey method of the NotesView class in LotusScript R5, I didn't really start using it through unfamiliarity until a couple of years ago, now its a staple part of my programming as an alternative to getAllDocumentsByKey.

There is nothing wrong with getAllDocumentsByKey and I use it all the time but if the view your looking at has hundreds or even thousands of records (documents to a Notes Developer) then scanning the collection you get back can be very slow. If however the document value is a view column entry then scanning the viewEntryCollection you get back from getAllEntriuesByKey is way faster, doesn't make the older code wrong or even unusable, you just need to know when to use each one.

Last week I recoded a process that had to iterate through a collection that turned out could contain anywhere between 0 and 22,000 entries, for 200 records it took 60 seconds to run. The new code finished in 2 seconds (I added temporary timing code) and more importantly took the same amount of time for 500 documents, its a major win for ten minutes of work including unit testing. The method was was available to the developers years ago when they wrote the sub, but they either didn't know about it or more likely had no confidence/ did not understand the performance implications.

We can only use what we are familiar with and have confidence in. The more development work you do the more likely it is that you will widen your experience and be able to use more features of a language to deliver quality software to your customers.

AndrewB
+1  A: 

We use XSLT heavily for many of our components. Most of the components are old) uses old parsers, which does not support XSLT 2.0, so we are still using XSLT 1.0 functions even though XSLT 2.0 provides many good functions.

24x7Programmer
A: 

In Verilog and VHDL (programming languages used to design chips), we always have to use the subsets that are "synthesizable" when designing the chip. The whole language can be used for test benches (unit tests).

Brian Carlton
A: 

While not strictly a "language feature" - one construct I avoid in C# is lock(this)

It's a leading cause of deadlock conditions in multi-threaded code since anyone can lock on the same reference.

LBushkin