41

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?

Nifle
  • 11,745
  • 10
  • 75
  • 100
Jonathon Watney
  • 20,248
  • 9
  • 38
  • 40
  • 1
    discussion not a question, voting to close – cletus Dec 08 '09 at 15:58
  • 13
    It's properly tagged, reasonably put, and not intended to be inflammatory. I wonder why we have to close this, rather than just leave it alone for those who are interested. If it has no value, it will be downvoted, and disappear to the bottom of the stack. – Sam Meldrum Dec 08 '09 at 16:03
  • 5
    Should be community wiki, but actually quite an interesting technical question. If it is closed I'll vote to re-open if it is made CW. –  Dec 08 '09 at 16:04
  • CW is the consensus - OP, are you listening? – Amarghosh Dec 08 '09 at 16:09
  • 2
    @cletus ... and "Why does every man and his dog want to code a blogging engine?" is not a discussion? I'd say that's less technical this question. – Lucas Oman Dec 08 '09 at 16:17
  • now that it's CW, I think it's acceptable -- a bit discussion-y but a good question and on topic – Jeff Atwood Dec 08 '09 at 16:53

19 Answers19

28

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

informatik01
  • 16,038
  • 10
  • 74
  • 104
Brian Ramsay
  • 7,536
  • 8
  • 41
  • 52
  • 2
    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 Dec 08 '09 at 22:27
  • @JonathonWatney Crockford has a lot of extremely arbitrary and bad advice, and should not be trusted prima facie as an authority on JS, but those three examples are all perfectly sound. I've *never* had to, nor felt any urge to, use `eval`, `==`, or `with` to do anything, with the exception of using `eval` for letting trusted users write JS in a browser's text field, which is the kind of thing it's designed for. Most of the time the "good" use of `==` is comparing two things casted to booleans, which is better done with explicit conversions (`Boolean(val)` or `!!`), then `===`. – iono Jul 09 '22 at 06:47
  • A **lot** of JS is now redundant with modern features. Honestly from an FP perspective, `for...in`, `for..of`, `for`, and `while` are redundant when 99.9% of the time your task fits a pre-existing pattern (which itself can be abstracted using just the `if` statement and function recursion). I pretty much never use the inbuilt loops and life is better for it. One of the most important *good* qualities of Lisps is that they *lack* almost all syntactical features except an essential, elegant subset. – iono Jul 09 '22 at 07:07
16

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.

  • 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 Dec 08 '09 at 16:40
  • 1
    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 Dec 08 '09 at 22:31
12

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
  • 108,003
  • 19
  • 148
  • 163
  • 3
    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 Dec 08 '09 at 16:24
  • 1
    @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 Dec 08 '09 at 16:30
  • @Neil: There should be only worthy ways to do it? :) – Adam Bellaire Dec 08 '09 at 18:24
  • @Adam That was of course a f*ckup on my part. But good catch on yours! –  Dec 08 '09 at 18:33
  • You can also use `goto` for improving tail call recursion. You could also use Sub::Call::Recur for that though. – Brad Gilbert Dec 09 '09 at 16:57
11

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
  • 414,610
  • 91
  • 852
  • 789
8

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
  • 15,597
  • 2
  • 44
  • 45
  • 2
    On the subject of PHP, many developers avoid some PHP features (e.g. `register_globals`) as they are considered to cause security risks. – MarkJ Dec 08 '09 at 16:10
  • @MarkJ True, although that feature is deprecated, along with other security threats, like magic quotes (ugh!). – Lucas Oman Dec 08 '09 at 16:14
  • 1
    This is actually a very good example of where featured of the language should be avoided to obtain good results. – Jeff Davis Dec 17 '09 at 15:11
8

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
  • 11,514
  • 5
  • 27
  • 40
  • 2
    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 Dec 17 '09 at 11:51
  • 6
    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 Dec 17 '09 at 13:02
  • 5
    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 Dec 17 '09 at 16:23
  • 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 Dec 17 '09 at 19:11
6

I avoid GOTO which in some circles is considered harmful.

Sam Meldrum
  • 13,835
  • 6
  • 33
  • 40
  • 4
    Depends on the language. In assembly you are almost required to use a goto. – Brad Gilbert Dec 09 '09 at 16:59
  • 1
    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 Dec 17 '09 at 04:11
  • 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 Dec 17 '09 at 14:01
4

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
  • 15,847
  • 1
  • 38
  • 65
  • +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 Dec 08 '09 at 16:54
  • 3
    Depends whether that "? :" is the ternary operator. – Steve Jessop Dec 08 '09 at 18:27
  • 3
    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 Dec 17 '09 at 04:53
  • 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 Dec 17 '09 at 13:36
  • @Bob Moore: try coding in *a language that shall not be named* (hint:starts with brain) – RCIX Dec 20 '09 at 08:33
  • Sorry, but what's "DRY"? (I'm not up on my TLA's here) – Andrew Shepherd Dec 20 '09 at 22:15
3

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
  • 14,639
  • 11
  • 62
  • 110
  • ANSI C and C++ are not subsets - vendor supplied extensions are supersets. –  Dec 08 '09 at 16:10
3

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 :-(

Kevin Shea
  • 920
  • 7
  • 12
2

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
  • 6,475
  • 4
  • 47
  • 59
  • Were there any situations where using reflection would have really helped? Or did you not really need it? – Jonathon Watney Dec 09 '09 at 16:06
  • 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 Dec 10 '09 at 14:44
  • 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 Dec 17 '09 at 05:14
1

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)

Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
1

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
  • 21,546
  • 5
  • 36
  • 52
  • 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 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 Dec 09 '09 at 08:37
  • 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 Dec 10 '09 at 15:50
1

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

RCIX
  • 38,647
  • 50
  • 150
  • 207
1

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
  • 31
  • 2
1

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
  • 474
  • 5
  • 20
0

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
  • 2,547
  • 1
  • 18
  • 27
  • 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 Apr 04 '10 at 13:48
0

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
  • 7,545
  • 5
  • 38
  • 47
0

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
  • 129,300
  • 32
  • 216
  • 265