Hacker News new | ask | show | jobs
by ggeorgovassilis 1489 days ago
> it is very unrestrictive

That makes collaboration hard. The freedom I have in putting my thoughts into code, uninhibited by syntax, types and conventions makes it nearly impossible for others to understand and modify my work.

4 comments

The freedom to flexibly put thoughts into code can be used to make code more readable, or less, it depends on the programmer. A significant code base in any language can turn into a hot mess

The perl coding team I was on made readability our #1 priority. We didn't use tricky or out of the ordinary syntax unless it was absolutely necessary (like unusual regex, etc), and in those cases we would document what was happening with comments and maybe a reference to the appropriate man page. We had a style guide, for a consistent look and feel. We paid attention to naming and commented blocks of code, so the reader would not need to run an interpreter in their head while skimming through the code. We'd seek feedback from each other. It worked out well. We had no problems reading our code.

We used the flexibility and expressiveness of perl to make our code more readable. We had the freedom to tailor the code to what we were doing, instead of the other way around.

Anything that "... depends on the programmer" is doomed to fill up with the output of a lot of programmers who were insufficiently disciplined. At some point the majority of the work becomes avoiding or working around or firewalling that output on your own projects. Telling people to just "Get Gud" at programming is a non-solution. The more I do this the more convinced I become that using a robot (compiler, linter, static-anlyzer) to enforce discipline is a good idea and the more difficult it is to escape that robot's gaze the better. Anything else is just going to cause massive pain later.
> The freedom to flexibly put thoughts into code can be used to make code more readable, or less, it depends on the programmer. A significant code base in any language can turn into a hot mess

If one learned how to collaborate on projects which, I think, the perl language does not incentivise.

(edit)

> The perl coding team I was on made readability our #1 priority.

I'd love to read more about that. Have you by chance documented your experience somewhere?

> If one learned how to collaborate on projects which, I think, the perl language does not incentivise.

I tend to think that things like high level documentation, organizing libraries and functions into good abstractions, comments, and naming make a bigger difference than the programming language chosen, within reason. The goal can be to make things as easy as possible for all developers as opposed to using every feature in a language.

There's a bunch of developer bad habits that can make collaboration hard. The processes and standards around development seem to make a bigger difference than the choice of language. So many coders don't bother with high level documentation, comments, or decent tests, nor do they spend the time to refactor their code as they go along to clean up readability issues. So many people just don't seem to want to bother, regardless of language. Often you have to fight management for time. I've seen atrocious and unmaintainable code in many languages.

> I'd love to read more about that. Have you by chance documented your experience somewhere?

My experiences grew to leading a team that were automating the reporting and deployment of complex configurations on a few tens of thousands of network devices, things like routers, switches, and voip, with all kinds of functionality for reporting, auditing, deployments, dry runs, debugging, etc. Perl is well suited to parsing and manipulating complex text configurations and outputs over ssh and interfacing to other related infrastructure applications.

We were able to process devices an order of magnitude faster than HPNA (java) and ansible (python). Our code was easier to read than code using these other systems, and more sustainable. We were able to handle complex projects like mpls cutovers, 802.11x and qos migrations and upgrades, etc. We'd translate complex network architecture standards to idempotent configuration management code. We also did a lot of reporting and compliance auditing. Some of it on short notice, most of it long lived.

Our project scripts read like pseudo code, a mix of perl and templating. The flexibility in perl helped us focus on representing our domain space as efficiently as possible. Our customers, who might be network engineers, managers, or compliance officers, could even read their project scripts, following the business logic, in this case the network architecture standards and/or reporting/auditing specifications.

Several of us were senior engineers, and there were always several junior engineers. Senior engineers tended to work on back-end library modules and more complex projects, at least getting them off the ground. Junior engineers were mostly contractors working on less complex projects. We made things easy for ourselves, tagging to-do notes by name and category in our source code. Everything was grep'able. Our processes were not in our way. Senior engineers would do code reviews, for readability, test coverage, and maintainability, usually just adding clarifying comments during a screen share and a phone call, maybe seeing a better way to arrange something, and be a second set of eyes looking for gotchas. We'd pay attention to the depth and complexity of our abstractions, try to keep user and developer documentation close to the relevant code, and have consistent naming for variables and functions. Seniors more frequently checked up on juniors. We'd discuss things as a group when need be. Customers were responsible for signing off on correct integration test outputs. I bet that well over half our bytes were comments, documentation, and tests.

My email address is in my profile, if anyone is more curious.

Thank you
> It worked out well. We had no problems reading our code.

That's not the relevant test, even for fairly large teams. More important is whether someone from another team (or more critically, a brand new hire) can read and modify the code.

That said, based on what you're describing, folks from outside your team ought to get comfortable pretty quickly too .

Teams do have conventions. There's code review. There are linters and pretty printers. There's even a standard set of default linter rules in perlcritic, taken mostly from Damian Conway's Perl Best Practices.

Perl has no problem from flexibility not shared by C, Common Lisp, JavaScript, Ruby, or Ada.

Writing in code is the same as writing in your native language. You are NOT writing it for the machine - you are writing it for the others like you. You are telling a story, and yes, it's hard.
How you use or abuse that freedom is entirely your choice.
This is true. The downside is that a couple days of not worrying about the understandability of your code can lead to a spiral that quickly gets out of control. Plus it makes expanding a dev team significantly harder since you really need people all on the same page of what readability means. Yes you can do things like coding standards, but the more free form the language the tougher such standards are.

That doesn't make a language bad, but it does change when and who can get away with using it. Same as the argument that comes up every time people talk about Lisp.

Is there any branch of engineering where "a couple days of not worrying" does not have the potential to be "lead to a spiral that quickly gets out of control"?
Languages with tooling that will yell at you if you are sloppy make it harder to get too out of hand. Part of why I've started learning rust is between the compiler and the linter I'm forced to ask if I'm being sloppy or not.
The languages that truly let you do anything you want flexibly invariably lead to incomprehensible ivory towers. It is why managers hate Lisp, it's why Perl is joked as write-once read-never.

The issue with the "DSL" is the third letter in the abbreviation: LANGUAGE. A language isn't just a specification of syntax. A language is a collective shared understanding between a sufficiently large number of people. Without that, it is a dead language.

Socially in programming, programming languages need to align to real-world concepts, because that is what enables the language to be understood by new adopters. And converging on those shared meanings is hard, because designers and lingo makers can't anticipate all the variations of understanding people will have.

Learning a language is hard. So every DSL I've encountered invariably forces me to be the compiler: what is this being translated into language-wise and what does it convert to. That is a big load, so your DSL better provide power and convenience to deserve it.

DSLs also run headlong into NIH/creator's advantage. The people/person that make the DSL and implement it will know it FAR better than any adopter will. And documentation is always lacking. So what is blindingly obvious to the core practitioners is very much not so to the noob.

You are limited by the average intelligence of the programmer at a cultural level. The lone mad scientist may produce amazing ideas, but all the groundbreaking technology happens because an army of people can be coordinated to implement something.

Lisp is basically a DSL factory, and everything is done via DSL. Can Perl7 do that better than Lisp? Is that a good or bad thing?

Well, it doesn't matter. Perl5 is what it is. Perl6 was a social failure. I doubt Perl7 will change anything.

> The languages that truly let you do anything you want flexibly invariably lead to incomprehensible ivory towers. It is why managers hate Lisp, it's why Perl is joked as write-once read-never.

I've yet to see that happen in a Lisp project. On the other hand, inflexible languages like Java lead to abominations like the Spring framework, where tons metaprogramming happens at runtime via reflection.

The thing about compile-time macros (e.g. Lisp macros) is that they can be debugged at compile time. For example, if you see a macro invocation, and you don't know what it does, you can just expand that macro right in your editor, and look at what code was generated.

People are always worried about DSLs, but most projects end up with their own DSLs. They're just often built out of functions, methods, objects, etc.

I think the real issue with understanding a project is learning the concepts, architecture, and abstractions they use. Knowing e.g. Go really well doesn't save you from having to wade through the giant pile of code used to express the program's intent. Abstraction is a way to get that complexity filtered down as close to the problem's inherent complexity as possible. Yes, you'll have to learn the abstractions, but if done reasonably well, that will still be much easier than trying to understand the non-abstracted version.

> People are always worried about DSLs, but most projects end up with their own DSLs. They're just often built out of functions, methods, objects, etc.

I wish there was a kind of super-upvoting that added one to the font-size of the comment you're upvoting, because I would absolutely super-upvote this comment.

> Abstraction is a way to get that complexity filtered down as close to the problem's inherent complexity as possible. Yes, you'll have to learn the abstractions, but if done reasonably well, that will still be much easier than trying to understand the non-abstracted version.

Absolutely. It's possible (arguably, too easy) to build a bad DSL, but the point of a DSL is to surface the inherent complexity of your domain so you can grapple with it on its own terms. Not using a DSL doesn't mean that complexity goes away; it just means you have to grapple with that complexity using coarser tools. You usually end up with a DSL-lite of types and functions that work in your domain, often with warts due to poor interactions with the host language's feature set.

For a lot of reasons, I'm a big fan of eDSLs, which aren't too much different from the DSLs-lite we usually end up with. But overcoming that impedance mismatch with the host is not easy. (That's one of the benefits of Lisp, I think -- very low impedance mismatch to overcome!)

I've gotten somewhat good at doing eDSLs in Java(!), where you want to keep things mostly idiomatic, unconstrained Java while still adding the novel behaviors you need for your domain solutions. But you're always going to have to wrangle the complexity of your domain, whether or not you involve a DSL in that effort.

Do you have a sample/example eDSL in java? I would find this interesting.
when i first heard that lisp was supposed to be good for making DSLs, my first thought was 'gross, i'll just stick to writing plain lisp thankyouverymuch'

but i think that's a misunderstanding- it's not a suggestion to make a mess with reader macros or whatever, its an observation that common lisp _naturally_ builds up to form the language constructs needed in your domain, simply by virtue of providing the tools and syntactic flexibility needed to construct them

another thing that seems to put off newcomers to cl is the parallax between the promise of a smooth, polished dev environment, vs the nuts-and-bolts-exposed nature of the core language itself (eg the infamous eq/eql/equal/equalp situation)- but i think this can be explained as how cl is _not_ a scripting language, and you are expected to paper over these edges as you define the system

cl gives you the best tools in the business to turn itself into a dev interface so clean it might as well be a DSL

Scheme is easy. Common Lisp it's a total distinct monster.