Hacker Newsnew | past | comments | ask | show | jobs | submit | more joncampbelldev's commentslogin

This comment would be less silly if the above hadn't made it clear that the "honour" is entirely from a western point of view.

It is then up to any japanese / non-western readers whether they give a shit about the honour conferred by some westerners.

Honour (like most things) is subjective and varies from culture to culture. Perhaps the day a universal register of honour is established you can post your comment again when some westerner applies to give honour to the japanese again.


So to say it "came into force" before its being enforced is at best a poor choice of words.


It was enacted at the EU (err: thingie) level in 2016 and required that all EU member states enact local legislation within two years, deadline 25 May 2018.

The EU is pretty complicated. Oh and by the way, the UK will 99.99999% maintain GDPR related statutes on the books, post Brexit. Either that or we are madder than I thought.


GDPR is a Regulation (the clue is in the name), not a Directive and doesn't require member states to transpose it in to domestic law.


Who mentioned Directive?


You did, because what you described is a directive. GDPR is not a directive. It does not require EU member states to do anything. Only country that needs to do something is the UK, since they're leaving the EU and want to convince the other member states that they're not naughty and they want to play in the same digital ballpark as the rest.



As a programmer approaching 30 I can confirm this for me. I am horrified that a company would prefer the long hours / low quality output of my earlier years compared to my current fewer hours / more thinking / higher quality output. I can only hope that I will improve a bit more as I cross over 30.

Who knows, perhaps I will immediately plateau and never learn or improve after 30 ;)


A lot of non-programmers simply can't discern the difference in output of a senior dev and a junior one. Like I recently realized, junior devs can appear massively productive because they can copy another part of the system and simply modify it. The output looks the same, but without that code made by someone with much more experience, they'd be lost.

If I'm brutally honest with myself, I used to think I was a lot better than I was.

I could fix any bug, I could add loads of new functionality. I was great.

What I wasn't appreciating was that the senior devs had set up an architecture for me to succeed. They'd laid out the code and made the loads of small decisions born of experience that meant I was basically coding with training wheels. I could simply look at how they'd done it and use the same technique. I didn't have to make any decisions, nor was I aware of the decisions they'd made.

What I've seen since is where someone's employed graduates to build something from scratch, those systems are a real mess. They literally code themselves into corners. Adding new functionality becomes harder and harder until they quit and the client has to call in the big boys.

I remember chatting to a senior contract game dev a year or two ago at a meetup, he was complaining that he never got to make a game. He always got called in at the end to optimise the game and do the best he could to fix the stupid architecture decisions the cheap, disposable, inexperienced game devs they'd used to make the game had made.


I can remember my first project as a junior front end dev watching the Architect setup the system for us. I never really appreciated him at first because we were doing a majority of the day to day work. Now that I am getting more mature I can appreciate the environments and standards he setup a lot more. Even things like continuous deployment tools, automated builds and the like help productivity tremendously.


EDIT: Big boys was a bad choice of phrase. I meant experienced developers, doesn't matter if they're a man or a woman.

Stupid edit lock.


I'm 49, still working, still learning new stuff all the time. You can't assume that someday you'll stop learning and start being productive. There is always something new to learn. Always. The next project is going to have new concepts that you haven't seen before. I still charge for it all. If the project requires a certain new technology, I'm not hiring someone new just for that project. I'll learn the new concepts, and then do the project.

The technology world is so rich with concepts now that you could spend your whole lifetime learning and never accomplishing anything. So why should I pay to learn something that only this project requires? Every project will have something new, therefore I can never make money? No, the cost of learning is built into every project. That's the way it is. Software development is not plumbing or carpentry. It's different, and learning is part of the cost of doing any project no matter how old or experienced the engineers are.


i applaud your nerve. the audacity of billing. i wish i felt more confident about that. that's great.

i feel that it's easier to bill for something like time spent learning the customer's unique (-ly confusing) data model, or for figuring out the product's requirements (since the company has little to no documentation of that).

OTOH, i feel less confident charging for time i spend learning about the vagaries and unexpected behavior of the android platform since "i'm supposed to know that" (and also since those problems are the android platform's responsibility)

i find the balance hard to strike sometimes. i compromise a lot.


Right now the industries are begging for programmers.

Companies from the US literally hire me to work remotely from my bedroom in France because they can't find somebody with the skill they need at the price they can pay. All of them are either taken or too expensive.

The situation is unlikely to change: the need for software is constantly increasing, but the rate we produce new developers and the quality of them is not following as quickly.

So get audacious. You are on the best side of the fence right now.


thank you for the encouraging words.


I'm 30 and feel like I've been in decline for at least 6 years. I used to be open to new ideas and techniques; now I'm so confident I know what works that I usually can't even bring myself to consider the alternatives. I used to be able to hold the whole system in my head and change things fearlessly; now I rely on the types to do that for me and check in an embarrassingly high number of errors whenever I try to work in Python (a language I used to be very productive in).

Perhaps our industry moves so fast that experience genuinely is a net negative?


Hahaha. At 30-32 I felt I was getting old.

Looking back I believe the reason was there is a subtle physical slowdown between late 20's early 30's, you are indeed slightly past your physical prime.

Then I hit 40 and felt young again.

But really, one shouldn't feel they are mentally slowing down at 30 or even 39. If that's the case you might need to check environment or what you are doing or some external factors.


> now I rely on the types to do that for me and check in an embarrassingly high number of errors whenever I try to work in Python

But you can write type hints in Python and get your tooling to tell you when something is wrong.

Personally I got mypy as a pre-commit hook, and vscode run it on each save, making my code lighting up like a xmas tree if I mess up.


Sounds really weird. If you know what works then you know you need something new sometimes. Never used a NoSQL database but I know when it's time to start using one. I might not, as some younger people would, default to MongoDB.

Also checking in errors seems a bit weird. Are you sure you are still motivated in what you do?


Just wanted to say thank you for mentioning rematch, it's exactly what I've been looking for.

I've built a couple of apps with redux and always wished it was closer to clojurescript's reframe in terms of minimal boilerplate. Rematch does exactly what I need.


Oh, cool. I'm glad to have turned you on to it. If you end up using it, I'd be interested in hearing what your experience is like.


Most likely the enforcement would be applied as a restriction on any future business done in the EU assuming the US company refuses to pay the fine.


Perhaps they meant it as a good example of the type of component to build systems out of, simple input->output. Unsure though.


I believe this is usually called the "Please think of the children" argument (or women in this case).

I imagine the person you are replying to is not a closet rape supporter, but they likely think that allowing every adult member of a population to arm themselves is not the ideal solution. I imagine you disagree with that view, but the way you have expressed yourself is the start of an emotional flame-war, not a discussion.


Arguments against guns are almost universally a think of the children argument though.


Not every argument about personal safety is a "think of the children" argument.

Guns are dangerous. Yes they can be used for self defense, but they are also dangerous on their own.

I believe that un-regulated guns are more dangerous (to everyone) than the danger of some subset of people being more vulnerable without them.

I'm not advocating for a ban, but heavy regulation about who can buy them, how, what kind of training they need, and verification of safe storage. Just like I'd expect my government to do with other highly dangerous things like explosives, some drugs, and more.


They are not dangerous "on their own" any more than an iron or a knife or an automobile or a bottle of tequila is dangerous on their on. All of those are dangerous in the hands of a bad person, an uneducated (about that object) person, or a mentally ill person. The object does not have inherent danger.


Yes and those things are (in my opinion) regulated proportionally to their "level of danger".

You can't anonymously own a car in the US, you can't (legally) buy one at a car convention then take it on the road without registering it. Larger knives have regulations and rules around who can buy them, and some are just illegal to own in many states. Tequila requires you to be over a certain age, and you can't buy it if you are visibly drunk.

These things are dangerous. Yes, they won't jump up and attack someone on their own, but even well educated sane good people have accidents with them, which is what I mean by these things being dangerous.

And just like with automobiles, I don't think banning them is the right move, but I do think requiring a "gun license" where you can prove that you know how to handle, store, and can show you have the skills to safely use a gun should be required, as well as registering and proving that you have a safe place to store them that is out of the reach of children, mentally ill adults, and theives.

Safe gun owners will need to do very little to get approved to continue owning guns, and many unsafe gun owners can be denied. Not to mention that increasing the "average" storage security would mean that less would be easily stolen reducing the number of unregistered guns available for purchase on a "black market".


One sticking point is gun owners seem completely unwilling to budge on any kind of gun registry -- which seems like a necessary starting point for any kind of accountability of ownership and an actual effective solution against straw purchases and illegal gun sales. Just putting this out here because I like how thoughtful your posts are and I am really stumped at finding a compromise -- ultimately I think there is no way to water down a gun registry (or even licensing) that the current gun lobby will accept, which is a disservice to safe gun owners.


That's what really sucks. For various reasons a gun registry will never really happen. It's too controversial due to America's past and founding.

I'm pretty sure that means we will either continue the path we are on now (which makes things "about" guns illegal, without making guns illegal or registering them), or we will leapfrog the registry and just outright ban most models or types or people from owning them.

Like you said many gun owners are letting perfect be the enemy of good here, and are unwilling to compromise on something that will allow them to keep guns for sport and self-defense in some situations. And that's going to lead to pressure building up to the point that their complains aren't going to matter, then they won't be listened to at all while the avalanche falls removing most or all gun rights.


It is usually encouraged on HN to argue with / respond to the points made by the person you in discussion with, not the vocal minority/majority out in the world who hold a different view.

Otherwise you get two people talking past each other. The fact that there are people who are fans of gun control AND express themselves immaturely with vapid politicised statements appealing to emotion doesn't excuse the almost trollish characteristic of the "do you think women should be defenseless against rapists" above.


Except if you're using immutable data, pure functions and explicit state there's a lot less room for OO which (as presented by ruby, java etc) involves mutable data accessed/changed via methods that conceal their state.


Nothing in the concept of OO enforces mutability. The paradigm doesn't enforce anything at all there. You want immutable objects that never changes once created? Fine, go for it.


I'm literally writing a blog post about this now (I'm building an objects system from scratch using only FP techniques in JavaScript... slightly eclectic ;-) ). The very interesting thing about this exercise is that immutability solves a huge host of problems in OO systems. As a very small example, even the diamond inheritance issue just goes away because nothing is ever updated. If B and C both have the base class A, you can safely instantiate A twice because it doesn't matter which one you use.

I'm about half way done. When I'm done, I'll post it on HN, but if you are interested here is what I've got so far: https://github.com/ygt-mikekchar/oojs/blob/master/oojs.org If anyone ends up reading it, I'm very happy to receive criticism, so feel free to leave an issue.


Sure, you can simulate immutability in Ruby or Python but it's not real immutability. It's just shallow freezing. The real point, however, is that immutability is not idiomatic in OOP languages. Objects are intended to store state and have it modified. It's not what a language can be made to do that matters. It's what is idiomatic.


And yet 99% of code written in Java, Ruby, <Generic OOP language here> is based on mutable objects.

Its not about what is possible, we're all familiar with the turing completeness of everything. It's about what is: the default + easy + encouraged in the ecosystem.


Javascript and Python are very popular dynamic languages, this doesn't make them good dynamic languages.

In particular OOP is very much helped by static types.

Clojure would a better example of a dynamic language that would not be improved by adding static typing. Namespaces, functions and immutable data (as well as pervasive use of data instead of wrapping it in classes) lessens the downsides I bump into continuously when doing javascript development.


I’ve tried Clojure a little bit and it seems like a nice language but I’m not convinced by the lack of types. Why wouldn’t you want types? How often can you reuse a function intended for ‘ints’ with some other type? The way I see it types provide important information to anyone reading the code after it was written as well as to the compiler making it possible to catch bugs early and generate more efficient machine code.


See my comments about Clojure.spec here:

https://news.ycombinator.com/item?id=16414942

This is all application specific, but for the types of apps I've worked on (large enterprisey OO apps) you often need various bits and pieces of domain data across different methods. So given some function, you either pass in DomainClass1, DomainClass2, DomainClass 3 (using a couple of properties of each) or you define a new class SomeSubsetOfPropertiesClass solely to call that single method. In the former case, the types do not serve as documentation for the reader as it's not clear what shape of the data is required for the function. In the latter case you're duplicating code (the properties and their types) and the class really has no meaning except as a struct to call that method.

Now that I've been working with Clojure for a little bit I find I'm able to write much more concise, testable functions and calling them is dead simple since I can work with the raw data, transforming it into the shape I need.


What you want to do is possible with a structural type system. In structural type systems, type compatibility is based on the structure of the type instead of the name (as opposed to nominal type systems).

An example in TypeScript:

     interface Named {
         name: string
     }
     
     class Person {
         name: string
         age: number
         // constructor here
     }
     
     function f(obj: Named) {
          // do something with obj.name
     }


     const joe = new Person('Joe', 25)
     
     // Compiles, even though Person has an extra `age` field
     // Person is structurally compatible with Named
     f(joe)
If you pass f() a class/object that doesn't have a `name` property of type string, the compiler would catch your error.


Interesting, except you're redefining the type of "name" in each each class by specifying "string". Also, Clojure.spec allows you to be much more precise about properties. For example, it must be a certain length, non-nil, or even match a regex (e.g. first letter starts with uppercase).


What do you mean by redefining? I'm not redefining the type of "name". If you want to get compile-time checking that `Person` implements `Named`, you can use `class Person implements Named`.

Even better than that, you don't need to use classes, you can use "normal" JS data structures. Extending the last example:

     const john = {
         name: 'John',
         age: 25
     } // No class involved

     f(john) // compiles

     const alice = {
         age: 25
         firstName: 'Alice',
         lastName: 'Jones'
     }

     f(alice) // compile-time error

Clojure.spec is cool, but I don't see how that is incompatible with static typing. You can still have libraries that check more complex properties at runtime.

EDIT: > Also, Clojure.spec allows you to be much more precise about properties. For example, it must be [...] non-nil [...]

TypeScript also handles nulls in the type system:

    function f(x: string | null) {
        if (x != null) {
              // tsc knows that inside this if, x can't be null
              return x.length 
        } else {
              console.log(x.length) // this doesn't compile, x is of type null here
        }
    }


In Clojure.spec, you spec out namespaced keywords once.

    (def email-regex #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$")
    (s/def ::email-type (s/and string? #(re-matches email-regex %)))

    (s/def ::acctid int?)
    (s/def ::first-name string?)
    (s/def ::last-name string?)
    (s/def ::email ::email-type)
Using those keywords you can define maps which specify shapes of data:

    (s/def ::person (s/keys :req [::first-name ::last-name ::email]
                        :opt [::phone]))

Functions have their own separate specifications. Here's one that accepts a person and an acctid:

    (s/fdef add-to-account
        :args (s/cat :person ::person :acctid ::acctid)
And must be called like this:

    (add-to-account {::first-name "John" ::last-name "Smith" ::email "john@smith.com"} 12345)
If you tried calling it with an illegal argument and it's instrumented you will see an error:

    (add-to-account {::first-name "John" ::last-name "Smith" ::email "abc123"} 12345)
    
    ExceptionInfo Call to #'scratch.core/add-to-account did not conform to spec:
    In: [0 :scratch.core/email] val: "abc123" fails spec: :scratch.core/email-type at:
    [:args :person :scratch.core/email] predicate: (re-matches email-regex %)
Here's the difference. What if I have another function that just accepts an email:

    (s/fdef lookup-user
        :args (s/cat :email ::email)
And another which looks up by last name:

    (s/fdef lookup-user-by-name
        :args (s/cat :last-name ::last-name)
And now imagine if you wanted to accept either an email or last-name (notice it does not match our person spec). Attempting to use interfaces would quickly get out of control. You'd have to create an interface for every single property and extend interfaces to form arbitrary groups of properties.


This is not easy to do in say Java which is significantly different from clojure (or how typescript enforces typing). In your example it appears that you're using the name field rather than the type Named to shape data that the function will use (this is in essence ducktyping)


I am using `Named` as an argument. In structural type systems, what matters is the type structure. It's not duck typing because it's checked at compile-time.

If I change the type of "Named" to have the fields `firstName` and `lastName` of type string, accessing any other property inside `f` (like `obj.nonExisting`) or passing objects that don't have those fields.


thanks! just to clarify, how do you manage the composition of these types? Do you create a structural type per API and potentially have the "same" types repeated multiple times?


Right, but that's nothing to do with types in general, mostly just Java and friends with unimaginative type systems.


To be fair, the OO example you give just sounds like bad design. It should be entirely possible to avoid having to pass giant bundles of state between different layers of your application, and even if you can't you should be able to define interface conformances on your DomainClass objects to make it clear which of their members are actually relevant in a given case.


Absolutely it's bad OO design. Because it's very difficult to do OO right at scale. For a larger application like many I've worked on (thousands of domain classes), it's much less risky to have an anemic domain model than attempt to model a very complex domain properly. I would imagine in the Java world most applications that use ORMs tend to lean towards anemic domain models that simply mirror DB tables.


One of the big benefits of clojure being dynamic is that everything is data (e.g. a map, set, vector or list).

This is what allows reuse.

- The vast core library of functions that manipulate those data structures can be used for everything in your program, cos it's all data.

- Most clojure libraries take and/or return data, reducing the need for clumsy adaptors, or even worse not being able to get at the data you need cos the library writer was really enthusiastic about encapsulation of everything they thought was of no use to consumers.

- You don't have a person class, you have a map with a first name and last name. Now the function that turns first + last name into full name can be reused for any other map with the same keys. (A rather spurious example, but a real one would take a large codebase and an essay to describe)

I can only recommend watching some of Rich Hickey's talks, particularly these ones, they're not entirely about types, but they express the above ideas much better than I can:

- Simple made easy https://www.infoq.com/presentations/Simple-Made-Easy

- Effective programs https://www.youtube.com/watch?v=2V1FtfBDsLU

- Are we there yet? (this one is more about OOP, but unless you're using something like haskell, idris etc its relevant for your type system of choice) https://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hi...


> One of the big benefits of clojure being dynamic is that everything is data (e.g. a map, set, vector or list).

What about this can't be done with types? Simple parametric-polymorphism gets you pretty far. Row types allow you to handle "maps as records" in a type-safe way. The rest is just having support for some kind of ad-hoc polymorphism so that you can re-use your functions on that small set of types (type classes, ML-style functors, interfaces, protocols, etc.).


Again, I would refer you to the Rich Hickey talks, I'm not very eloquent on this. I think its about the manual overhead that constructing your hierarchy of types, plus the cognitive overhead of doing all the fancy things in your brackets.

I'm familiar with the advantages of type systems (my progression was Java -> Haskell -> Idris) but I found my personal productivity (even in larger systems built in a team) was best in clojure. I didn't feel that the guarantees given to me by the type system were worth the mental overhead, a lot of people feel differently (you amongst them I'm guessing :p)

As a closing point, if I were to ever build something that truly had to be Robust in a "someone will die if this goes even slightly wrong" way, I would reach straight for Idris and probably something like TLA+. However most of my development revolves around larger distributed systems communicating over wires, still resilient but in a different way. Mainly I use clojure.spec in core business logic and at the edges of my programs, for generative testing and ensuring that the data flowing through the system is sensible.


The data types in Clojure can be very easily (and better) expressed in (say) Haskell. For example: http://tech.frontrowed.com/2017/11/01/rhetoric-of-clojure-an...


The main issue is that Haskell is not a data-oriented language by default, this means its no fun to push it to be that. For example, I also have to use java in my job, I use persistent (functional) data structures all the time, but Java is not built for it, its not fun. (Although definitely more fun that using Java's mutable structures, ewww)

Also I personally find that to be too much overhead and ceremony in return for some type checking at compile type, as opposed to spec checking at runtime.


> The main issue is that Haskell is not a data-oriented language by default

What do you mean by "data-oriented language"?


In the grandparent comment's link (showing clojure data in haskell): I'm pretty sure that is not how people code in Haskell, its not how the libraries are usually designed etc etc. Using only data is definitely possible in Haskell, but it's not encouraged by default, the core abstractions are used for concretions of information.

In the same way you can do immutable and functional stuff in java, it's not going to mesh with the rest of the ecosystem or language around you.


>I’ve tried Clojure a little bit and it seems like a nice language but I’m not convinced by the lack of types. Why wouldn’t you want types?

Clojure has classes and types. How can it be untyped?

Machine language is untyped.


>Javascript and Python are very popular dynamic languages, this doesn't make them good dynamic languages.

JS in particular is a very bad example of a dynamic language, the other "very bad" example being classic PHP.

This, mostly, because of weak typing.

Many of the problems attributed to C, a statically-typed language, are also due to weak typing.


> Namespaces, functions and immutable data (as well as pervasive use of data instead of wrapping it in classes)

There are plenty of functional programming languages that believe static typing is a significant added value even under these conditions.


And some believe that the added value is not worth the trade off in mental overhead and ceremony. We are surely both aware of the various, numerous and flame-war arguments for static vs dynamic typing. (For my side I can only recommend Rich Hickey's talk "Effective Programs", he says it better than me)

My main point was that dynamic typing should be judged by it's best implementations, not by JavaScript. For example, I would not judge static typing by Java or C++.


>> would not be improved by adding static typing

Well, that's a matter of opinion, even by long-term Clojure veterans. There is a reason Core.Typed was developed, though it hasn't been maintained recently. The fact that Rich felt the need to give the keynote at the last Clojure conference about the dynamic vs static issue shows that it is still a highly debated topic within the Clojure world.


I think the debate may be leaning towards dynamic.

- The aforementioned keynote highlighting the various reasons Rich chose to make it dynamic.

- CircleCI (one of the major users and propronents of core.typed) dropping it.

- The introduction of spec as an alternative for some of the reasons people use type systems (its certainly not a drop in replacement and doesn't intend to be).

- Spec allowing different kinds of verification not possible with a type system on its own.


I find it interesting that Rich (and other Clojure people) feel they need to continue defending themselves again and again. While strongly typed language communities usually don't feel the need. There must be some deep doubt in the Clojure community that triggers this.


I think it's more a acknowledgement of the current state of popularity of languages and an attempt to win people over rather than a manifestation of latent doubt.


Forgive me, but your comment seems a little disingenuous with the way it generalises the static community (every static language??) vs the clojure community.

Many of the comments on this page show why Rich gave the keynote. Because the same advantages of type checking are put forward as a reason to not use clojure over and over. They're not wrong, static typing has advantages, but I see little acceptance of any tradeoffs (or even acceptance that such tradeoffs exist: concretion of information, coupling of distant components by shared types etc etc etc I'm just paraphrasing the keynote).

He was highlighting the value proposition and tradeoffs of: being data-oriented, being dynamic and clojure.spec niceness. He felt the need to do this because he clearly felt that some people who were wavering about clojure were unsure why it was dynamic: "can't we have all this great stuff AND static types". He wanted to say "yes quite possibly you could, BUT here's the reasons why I didn't add types".


I'm saying this as a massive clojure fanboy: java.util.concurrent is an amazing set of concurrency utilities and is the building block for many of clojure's concurrency features. It's definitely worth knowing when writing performant java AND clojure (you can wrap the little bit you need so you don't have to scatter java interop all over your codebase). Sometimes a (swap! atom fn) doesn't cut it.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: