Ask HN: Do you mostly program in a non-FP or non-OO style? Why?
69 points| open-source-ux | 8 years ago
Or are you using an FP or OOP language but rarely use the FP or OOP features? If so, why?
69 points| open-source-ux | 8 years ago
Or are you using an FP or OOP language but rarely use the FP or OOP features? If so, why?
[+] [-] falcolas|8 years ago|reply
OO: Only rarely, and only where it really makes sense. Most programs I work on are not complex enough to justify the overhead (boilerplate, cognitive).
FP: I use this more, but again, only when I can really justify the added cognitive overhead.
You'll notice the two references to cognitive overhead: I have adapted the "write for a 6th grade level" idiom into programming. I want as many people to be able to pick up the code and modify it as possibly can. I work with everything from interns to decades plus veterans, and my code must be grok-able by both. Pure FP tends to confuse interns, and veterans have a tendency to hate the layers and layers of indirection and abstraction OO brings into a program.
Normal and boring old "an imperative main method with functions" tends to be the least offensive and most understandable to all parties. Compromise r fun.
[+] [-] qorrect|8 years ago|reply
I generally agree with "use only as much cognitive overhead as needed to get the job done" ( I'm enjoying that term ) - but it seems like a slippery slope that could slowly bring everyones abilities down to the least capable developer.
[+] [-] solipsism|8 years ago|reply
The common way to do this in OO (and yes this very much includes Go, whose standard library is incredibly OO) is to have C depend on an interface instead of a concrete X. Then you have full freedom to test C very robustly and at different abstraction levels.
So how do you cope with this in your code? "Imperative main method with functions" doesn't sound like it leaves room for proper testing, unless the code doesn't do much.
[+] [-] llogiq|8 years ago|reply
I don't embrace the FP style either because while I generally limit mutation (`final` almost everywhere), I use mutation where it leads to code that is easy to understand, which would be exceedingly "clever" in FP style.
[+] [-] hyperpallium|8 years ago|reply
It's simpler, more flexible, less verbose and easier to follow than a full-on OO style. A great example is the early calculatoe e.g. in ed 2 vs 3 of the compiler "Dragon" book: older uses C, later uses OO java... and it's so much worse.
However, OO is great for wrapping up modules of functionality for which you've understood and settled on an informed architecture (or you just need to sweep repetitive boilerplate away).
I think inheritance is just about completely useless (but not quite completely), and (java) interfaces are great - if you have more than one implementation.
Big, multi-person projects are a different story.
I don't use much fp-style, except where recursion is natural (e.g. parser combinators); or for plug-in functions (hardly fp though).
[+] [-] morbidhawk|8 years ago|reply
I came to the realization I didn't even need a lot of the language features for what I was doing and decided to switch it to C to not have to maintain various versions of the library and it was a steep learning curve but I've come to really enjoy the simplicity but powerful capabilities of C.
[+] [-] analog31|8 years ago|reply
I do some microcontroller programming, and it's usually straight C. The hardware registers are all global, and their contents change based on external stimuli, so that kind of rules out the idea of stateless programming.
The earlier versions of Visual Basic had kind of a compromise, where it came with a lot of pre-made objects, and you could create objects if you got the special kit, but the casual programmer was only expected to use objects. I kind of adhere to that idea when I write in OO languages such as Python.
I use OO sparingly when programming Python, often to encapsulate hardware functionality, but then use those objects within programs that still look procedural.
I avoid using inheritance, mainly because I don't trust myself to do it in a maintainable way.
[+] [-] Animats|8 years ago|reply
I've tried functional programming in Rust, but it's not going well.[1] I don't like the "x.and_then(|foo|).if_even(|bar|).except_on_alternate_tuesdays(|baz|)" style. Rolling your own control structures is not good for readability.
[1] https://github.com/John-Nagle/rust-rssclient/blob/master/src...
[+] [-] nnq|8 years ago|reply
2. "Grand scale Functional characteristics" - exposed API should try and have "referential transparency" and "composability" (you can write systems with "functional properties" in languages like PHP just fine btw.)... find not much benefit from "small scale / low level" FP.
3. Wrap stateful algorithms & other code rich in mutable variables in either (a) referentiaally transparent functions or (b) shallow objects that make it obvious how and when state changes.
4. Avoid the "islands of functional purity in a sea of objects" pattern like the plague - it results in large scale intellectual masturbation at the small scale, and incomprehensible systems at a large scale, your monadic fantasy is useless when stuck inside the method of a 8-levels-inherited monster object... functional is important on a whole-system level, a 10 line method is easy to understand even if it mutates local variables all over the place
In theory FP would be great at all scales when coupled with a good type system... but I've never got to work on projects in languages like Haskell or Scala and I'm not sure I could handle the cognitive overhead of it.
Oh, and don't use Exceptions, ever!
[+] [-] nnq|8 years ago|reply
[+] [-] zaptheimpaler|8 years ago|reply
I tend to see programming as writing. The style of writing depends very much on the context and the audience.
I lean towards "basic" FP (immutability/pure functions/composition) but none of the heavy category theory concepts (anything with types that are too complex). Its mostly procedural with a hint of FP.
Most things should be functions, most higher level things (classes/packages) should be primarily ways to bundle related functions.
Prefer to maintain a clear separation between data & operations on data or structures imposed on top of it. I dislike the OOP approach of bundling data + transformations together. Also dislike inheritance because that is baking one particular structure into the definition of data.
[+] [-] morbidhawk|8 years ago|reply
It's almost a weird paradox: OO/FP focuses on reusing code yet imperative/procedural code (ie: C) does not reuse code but is itself the most reusable code. You can't have your cake and eat it too I guess.
[+] [-] jstimpfle|8 years ago|reply
I still like to program in C and make my own thin abstractions / "runtime", tailored to the task at hand, and using only minimal dependencies. That way it's much easier to have only essential dependencies, not accidental ones. It's such a relief seeing a couple thousand lines of cleanly modularized C code compile almost instantly.
For example, by putting a char * into a struct definition a dependency on a more clever string type can be avoided. All that it takes is delegating memory management decisions to another place. Which is actually very beneficial, since most code shouldn't be concerned with mutation or especially allocation.
[+] [-] itwy|8 years ago|reply
[+] [-] messe|8 years ago|reply
Other than that, I use Mathematica quite a bit for playing around with ideas. I've tried sympy, and I hoped to switch to it but it's just not as fluid and integrated.
If I'm coding for fun I tend to come back to FP and OO, I'll use either Haskell, Python or CL. I've been meaning to make something using Rust for a while. I'm planning on building a fermentation chamber (and perhaps a kegerator depending on my budget) for homebrewing at some point over the next year; I'm thinking that I might use Rust for the temperature controller.
[+] [-] glup|8 years ago|reply
[+] [-] _0w8t|8 years ago|reply
For side projects and for small Python code at work recently I have been applying data-oriented programming patterns. So far they worked surprisingly well.
Perhaps this is because one have an overview of the whole program state that is not hidden behind multiple layers of OOP abstractions and there is no mix between data and code, as happens with functional style.
[+] [-] ajarmst|8 years ago|reply
While I sometimes teach programming in C# and C++, my main responsibility is our Algorithms and Data Structures courses, for which we've kept using plain old C. From a teaching perspective, it's a great language for teaching fundamental algorithms and data structures. The students are also able to leverage that work into later courses on microcontrollers and embedded systems.
For my own work, I tend to mostly be writing code for somewhat idiosyncratic one-off data processing (I'm currently working on a genetic algorithm for class, student and professor scheduling) or embedded systems. The former I generally work in Common Lisp (SBCL)(although I do keep promising myself to learn enough Clojure to see if I prefer it). This is probably because of the way I think, as I tend to be comfortable building a system from bottom up, moving the data representation from the general facts I start with toward a representation that meets my needs. I actually came to CL pretty late, about a dozen years ago, but it really seems to suit me, possibly because I'm still primarily a command-line person. Being an emacs user certainly was a strong influence, too, although I don't hack elisp very much. I should add that I do often use CLOS, especially when working with more structured data, so I do use some OO, although it's mostly just to provide a more convenient interface to some complicated data type.
For embedded development, I still work almost exclusively in assembler or C, with less assembler every year. I tend to be working on pretty low-powered special-purpose devices, so code reuse and robust interfaces don't add much value, but close control of exactly what the hardware is doing does. This was normal in that domain until comparitively recently, but the power of even cheap devices and the availability of libraries mean that there are a lot more options. I expect that I'll continue to work mostly in C out of familiarity and inertia, but I will admit to having recently bought some Lua books with the intent of trying it with ESP8266.
[+] [-] lj3|8 years ago|reply
Was this written in a book somewhere? I keep hearing it from people, but nobody's able to really explain why. OO is terrible for GUIs IMHO.
[+] [-] 5ilv3r|8 years ago|reply
[+] [-] mlok|8 years ago|reply
[+] [-] nnfy|8 years ago|reply
My problem with non OOP in a language like python is that I have trouble scaling large apps and interacting with large libraries, because without type information enforced by the compiler, there is too much left to my own working memory, compared to a strongly types language built around OOP.
What's more, without rigid encapsulation I feel im exposed to an excess of internal code any time I need to look up a parameter or kwarg. Never mind the trouble of navigating five files feel through aliased method names...
As examples, consider matplotlib or tensorflow. Extremely easy to use once you know where everything is and what params to pass where, but I can't help but feel that it would be easier with stronger OOP.
I feel like I have not yet learned to think in a pythonic manner, but after a few years I'm not sure if I every well. As an aside, I just dont understand how python doesn't cause problems for devs when it scales...
[+] [-] gt565k|8 years ago|reply
We have a proprietary database called LogicBlox, that allows us to push all business logic down to the database layer, and almost entirely avoid having a service layer, or at least a very lean one. This allows us to address efficiency problems purely by optimizing database joins between predicates (tables).
Our data is highly normalized (6NF).
http://www.logicblox.com/learn/
[+] [-] lgas|8 years ago|reply
[+] [-] rasjani|8 years ago|reply
For data iteration, i prefer functional style (even in python, even after years list comprehension just feels so wrong).
[+] [-] imh|8 years ago|reply
[+] [-] cratermoon|8 years ago|reply
[+] [-] tscs37|8 years ago|reply
I kinda tend to start with a OOP style for the data models and a small shake of FP for the functions but change this according to my needs.
There is no one true style for programming, there is only tools for a task and using the best or good enough tool is the only important thing. (Though sometimes it's fun to use the wrong tool and see how it goes)