other-languages

here be heresies and things we have to use for work
2016-05-07T01:24:20.000212Z

plain ol' waste of time, in my case, as I'm i large part writing tests to catch things i would have wanted the compiler to, or to document how the system works for the next poor sod.

2016-05-07T01:25:13.000213Z

the way i was taught to do tests is a sort of a cross between 'ensure the system behaves as it should' and 'document how this works for the next person'

2016-05-07T01:26:31.000214Z

https://clojurians.slack.com/archives/other-languages/p1462567819000164 << another way to say this is "max dynamicism or max static"

2016-05-07T01:27:10.000216Z

i only ever wrote a few very small systems in CL, but the SBCL compiler was just so on top of things if i bothered to specify argument and return types.

2016-05-07T01:28:28.000217Z

the CLOS dispatch system in combination with the compile-time typechecking gave me an absurd amount more confidence in the code that I was writing, at least compared to clojure.

seancorfield 2016-05-07T01:31:26.000219Z

And then there’s the whole question of whether you’re writing tests first as a way to guide the design of your code (TDD/BDD) or writing code first and then writing tests to verify (a subset of) its behavior.

2016-05-07T05:01:36.000220Z

@seancorfield: how would you characterize schema's behavior in those two senarios?

seancorfield 2016-05-07T05:03:14.000222Z

That "question" wasn't in the context of Schema, to be honest, and I'm not really sure what you're asking...?

seancorfield 2016-05-07T05:10:23.000223Z

What do you mean by "Schema's behavior" in that context? (of TDD vs after-the-fact unit testing)

2016-05-07T05:32:09.000224Z

ah, i misread then.

sveri 2016-05-07T06:17:27.000226Z

@bvulpes: @seancorfield for me the main reason to use Schema is that I can see what my function returns and the parameters it takes. Especially regarding the structure of the maps and vecs.

borkdude 2016-05-07T06:19:15.000227Z

yes, it's useful documentation

borkdude 2016-05-07T06:19:33.000228Z

which is actually checked

sveri 2016-05-07T06:21:34.000229Z

Also i recently read somewhere that tdd brings a lot of value regarding Bugs and pays out in the long term. Because to get started with it, development takes some more time than writing Tests after the code.

borkdude 2016-05-07T06:21:44.000230Z

Maybe it would be an idea to have a tool which stores sample arguments (during tests/dev) to some database that you can later use to infer some types/shapes in the documentation

seancorfield 2016-05-07T06:27:51.000231Z

Two words: good naming.

seancorfield 2016-05-07T06:28:52.000232Z

Seriously. Use good names so the code is self-explanatory. The less "code" you have to read to understand the actual code, the better.

seancorfield 2016-05-07T06:29:42.000233Z

Schema isn't bad in that regard. It's fairly minimal annotation, but it's still a shift from standard Clojure to Schema-flavored Clojure.

borkdude 2016-05-07T06:30:43.000234Z

@seancorfield: I was thinking of a function that expects a nested hash-map I had in a CRUD app which would then pass it to clojure.java.jdbc, no amount of good naming documents the expected shape

borkdude 2016-05-07T06:31:24.000235Z

(defn store-person [person] ...)

borkdude 2016-05-07T06:32:16.000236Z

map destructuring of course helps

seancorfield 2016-05-07T06:32:22.000237Z

And I think if you're doing TDD/BDD, where you write the tests first, you have the opportunity to work on language, as in "the words used to describe the domain", and that -- executable "specifications" -- provides rock solid "documentation" about the intent of the code.

seancorfield 2016-05-07T06:33:18.000238Z

@borkdude: Why doesn't person signal that? Is it the word used in your business domain? Is it the word that everyone in your company understands?

sveri 2016-05-07T06:33:28.000239Z

@seancorfield: One example: https://github.com/kumarshantanu/clj-liquibase this lib is a wrapper around liquibase and will do awesome stuff for you. But, its column shape looks like this: [:id [:varchar 30] :null false :pk true :autoinc true]. I never figured out a better name than column-description or something like that but still always had to look up how it looks exactly, because in your function you only see code like this (first (second ...))

borkdude 2016-05-07T06:33:54.000241Z

@seancorfield: what @sveri says

seancorfield 2016-05-07T06:34:18.000242Z

But the problem there @sveri is that the library isn't providing a domain-specific way to buil those values.

seancorfield 2016-05-07T06:36:11.000243Z

I suspect that API was not Test-Driven ... if you have to "guess" what the shape of the data is, you haven't written tests around passing that data in ... or at least you haven't thought about that use case. No disrespect to Shantanu -- he produces great software.

borkdude 2016-05-07T06:36:56.000244Z

@seancorfield: I had tests, but then I had to look up those tests. I think it's convenient to have the shape near the function arguments and that is what Schema gives me

borkdude 2016-05-07T06:37:21.000245Z

I'm lazy and don't want to search

seancorfield 2016-05-07T06:38:30.000246Z

Different folks like different approaches. Schema doesn't work for me but it's not horrible, and I can see why other folks seem to love it.

seancorfield 2016-05-07T06:41:41.000247Z

I think my ideal type system would be one that allowed completely opaque types to be defined, that you could refine later on.

seancorfield 2016-05-07T06:43:41.000248Z

No language exists like that yet as far as I know.

seancorfield 2016-05-07T06:48:41.000249Z

(this goes back to @ericnormand's comment about types being "the future", not the present 😆 )

👍 1
2016-05-07T06:50:28.000250Z

naming is an incredibly useful tool. having function signatures (with args as named in their source definitions) displayed unobtrusively in my IDE alleviates a megatonne of jumping around through code.

2016-05-07T06:51:02.000251Z

granted that does nothing for the "and precisely what shape did a person have again?" problem

seancorfield 2016-05-07T06:53:30.000252Z

@bvulpes: but neither Schema nor core.typed help you with that while you're actually writing the code in your IDE, right?

2016-05-07T06:53:52.000253Z

gosh no

seancorfield 2016-05-07T06:55:27.000254Z

(and, yes, I know it helps with Java / Scala in their IDEs, when you get popup help after foo. when the IDE can deduce what foo might be ... but (:something data) doesn't really lend itself to that sort of popup help 😄 )

2016-05-07T06:57:34.000255Z

you mean those weird function calls where the first argument is to the left of that odd period character?

seancorfield 2016-05-07T06:58:09.000257Z

As a side note, whole program analysis with a unification engine running in your IDE could help with Clojure but, boy oh boy, that would be a lot of work!

2016-05-07T06:58:47.000258Z

myeah and i'm going to guess nigh-impossible without a type system.

2016-05-07T06:59:49.000259Z

anyways, i make do with the function arg names in the minibuffer. not great, but gets the job done.

seancorfield 2016-05-07T07:00:16.000260Z

@bvulpes: well, if you seen (:something data) you can infer that data is a map with an (optional) key :something (depending on the surrounding context) so with an entire program to look at, you can infer a lot of things ... potentially ...

2016-05-07T07:00:45.000261Z

sure, but i tend to write the keywords first, and what precisely is the IDE going to suggest in that case?

2016-05-07T07:00:58.000262Z

every map ever used in my proggy that had that key?

seancorfield 2016-05-07T07:00:58.000263Z

When I worked on that in my research (early 80's) it was certainly an interesting problem to work on.

seancorfield 2016-05-07T07:01:36.000264Z

Well, the IDE could look at (:foo bar) and say "Hey, bar probably doesn't have a :bar!"

2016-05-07T07:01:51.000265Z

@seancorfield: i would not even argue that the state of the art in the eighties trounces any technology i've ever deployed to any production environment ever.

seancorfield 2016-05-07T07:02:08.000266Z

When you have the whole program, you can do a lot of stuff.

2016-05-07T07:02:46.000267Z

i can see it.

seancorfield 2016-05-07T07:02:52.000268Z

As another example (and this was a really painful project), I was involved in a three-pass C language analyzer that converts programs to Malpas, for formal static analysis.

2016-05-07T07:03:05.000269Z

hahaha go on

seancorfield 2016-05-07T07:03:23.000270Z

Part of that was to eliminate all global variables by making them arguments that were passed recursively down through the entire code chain. DYAC!

seancorfield 2016-05-07T07:06:21.000272Z

Pointers had to be turned into enums (over the set of things they could refer to) as well.

seancorfield 2016-05-07T07:06:45.000273Z

We have a long way to go.

borkdude 2016-05-07T07:07:33.000274Z

"Different folks like different approaches. " -> that's exactly why some people complain about why Scala doesn't scale in some companies 😉

2016-05-07T07:16:36.000275Z

https://clojurians.slack.com/archives/other-languages/p1462602742000237 , https://clojurians.slack.com/archives/other-languages/p1462602094000229 << a bit of heterodoxy, and not a best practice in any sense, but on my last few projects i've regarded (my) tests as constraints on the possible spaces through which the program can transition. i generally write them in parallel with the code that i'm writing (which granted, people with the budgets and timelines to write as many test of however much verbosity they want tend to regard as sloppy or complected tests), and use them to pin down the behavior that i demand of the system under test.

2016-05-07T07:17:28.000277Z

to put it another way, i hold a lot of the program in my head at once, and use tests to pin down details and compound behavior.

borkdude 2016-05-07T07:18:24.000278Z

This seems to be the thought of Uncle Bob's latest blog, which I didn't find very convincing on its own

borkdude 2016-05-07T07:18:44.000279Z

TDD > Static Typing

borkdude 2016-05-07T07:18:56.000280Z

But maybe I haven't done enough TDD then

2016-05-07T07:19:45.000281Z

you wouldn't cut a chair leg on a mill, would you?

2016-05-07T07:20:02.000282Z

@borkdude: "giving up on TDD"?

borkdude 2016-05-07T07:20:44.000283Z

@bvulpes: who are you quoting here?

borkdude 2016-05-07T07:20:55.000284Z

@bvulpes: I don't know this saying, what does it mean?

2016-05-07T07:22:18.000286Z

by "Uncle Bob's latest blog" do you mean the post titled "Giving Up on TDD"?

2016-05-07T07:22:33.000287Z

or "Type Wars"?

borkdude 2016-05-07T07:22:55.000288Z

"Type Wars", or isn't that his latest

borkdude 2016-05-07T07:25:27.000290Z

http://reborg.tumblr.com/post/143899403083/clojure-weekly-may-5th-2016 "but the major source of pain for the projects I work on has been people not knowing how to structure their code"

sveri 2016-05-07T07:37:50.000292Z

@borkdude: like I said, there was a paper that found significant gain regarding Code quality when doing strict tdd. If I remember i will look for it at work on Monday. Whereas i have not found a paper yet that Shows gains in the typed vs. Dynamic debate, no matter the side.

borkdude 2016-05-07T08:10:47.000295Z

@sveri: cool, I'll be happy to read it. I think the mistake that Bob Martin makes is that TDD somehow replaces static typing. It depends on which goals you have in mind with static typing. The set of goals of each are overlapping, but not identical.

tjg 2016-05-07T09:34:14.000300Z

There are companies where it’s possible to compare tools. For example, Rewe Digital has like 15 dev teams across the JVM, including a Clojure (hopefully 2 soon) and Kotlin team. (And they just hire senior devs, which maybe normalizes things a bit.)

tjg 2016-05-07T09:34:19.000301Z

However, incompatible language cultures usually hinder communication...

tjg 2016-05-07T09:46:36.000302Z

(Fortunately, the Clojure team is considered very good, which I verified with managers.)

borkdude 2016-05-07T10:44:26.000303Z

Clojure devs are usually very good. A lot of beginners give up because of the syntax (superficial), mysterious stack traces (takes time to get used to if you don't know Java), not being able to set up your dev environment, not getting the idea of working with a REPL, etc. When you get passed all that, you're pretty good already 😉

borkdude 2016-05-07T10:45:14.000304Z

I remember fighting with getting the classpath straight in Emacs + slime/swank in 2009 and not giving up until it worked. I'm not sure if I would do that again if I was trying a new language.

borkdude 2016-05-07T10:46:55.000307Z

Of course Clojure devs are usually good because of other reasons too, being able to appreciate the design of Clojure for example and the ideas behind FP in general

borkdude 2016-05-07T10:50:34.000309Z

One of the smartest students I trained really got Clojure. Now he is a Haskell fan and knows an awful lot about FP, much more than me.

sveri 2016-05-07T11:06:44.000312Z

@tjg is it really the incompatible language culture that hinders communication? Or more the objections developers have against other languages that leaves them closed to different ideas / approaches of problem solving? From my point of view differences in culture usually enrich communication instead of hindering them, as long as people are genuinely interested.

sveri 2016-05-07T11:12:10.000313Z

@borkdude: Ok, before I forget it I just went through my mails and found the link: http://research.microsoft.com/apps/mobile/news.aspx?post=/en-us/news/features/nagappan-100609.aspx

sveri 2016-05-07T11:12:18.000315Z

This was my summary from back then:

sveri 2016-05-07T11:12:35.000316Z

1. Code Coverage is no indication for the quality of code. Regarding code coverage it is beneficial to achieve higher coverage of complex code. 2. TDD: produces 60 – 90% better code in terms of defect density than non TDD teams. Although TDD teams take longer to complete projects about 15 to 35%. 3. Use of assertions: No numbers, but the paper finds a that higher assertion density leads to a lower fault density, stating at the same time that the statistical data is not significant enough. 4. Organizational Structure: “Organizational metrics, which are not related to the code, can predict software failure-proneness with a precision and recall of 85%”. This is significantly higher than other metrics such as churn, complexity or coverage. 5. Geographical Distance doesn’t matter. The data found had no statistical significance

sveri 2016-05-07T11:13:32.000317Z

The most interesting part for me were point 2 and 4 whereas the other points did not surprise me at all.

sveri 2016-05-07T11:15:02.000318Z

Also its nice for a developer to have some numbers like these. You can approach your manager now and tell him that he can have less features in better quality or more features with more bugs and in the end its up to him to decide that.

tjg 2016-05-07T12:08:52.000319Z

@sveri: Yeah, probably closed to different ideas/approaches.

seancorfield 2016-05-07T18:33:50.000322Z

@sveri: thanks for linking to that. I read it before but it bears rereading and some things run counter to intuition and some things confirm my intuition.

seancorfield 2016-05-07T18:34:50.000323Z

TDD is a hard topic to discuss because there are a lot of people who have tried it and failed to find value in it, or at least failed to find enough value.

seancorfield 2016-05-07T18:37:48.000324Z

Uncle Bob has talked about some of the reasons why, as have Beck and many of the others in the Agile / XP / Software Craftsmanship camps. And that's why you hear a lot of "If you think TDD doesn't work then you're just not doing it right". A sentiment which, while most likely accurate, really helps no one (since, on the face of it, it's the True Scotsman argument which is a known fallacy).

seancorfield 2016-05-07T18:40:13.000325Z

Many years ago, I worked at a company that built static source code analyzers. As QA tools. They could enforce coding standards but they could also find bugs -- and via statistical analysis of source code metrics they could predict maintenance hotshots and sometimes highlight some very bizarre code bugs.

seancorfield 2016-05-07T18:41:12.000326Z

The analysis wasn't concerned with types but with idioms and measurable aspects of the code.

seancorfield 2016-05-07T18:42:45.000327Z

The tools were easy to sell in Europe and Japan where ISO 9000 held sway but were very hard to sell in the USA due to the mindset of programmers here. This was in the early 90's.

seancorfield 2016-05-07T18:48:59.000328Z

Tying this back to TDD, and also to other languages, and to that MS research: code quality needs to be baked into your system from the start and that needs to be an organizational thing and a process thing. The programming language doesn't matter as much as the approach. Type systems catch a certain class of programmer error but they don't catch others. TDD, done properly, can help you design "correct" software in any language ("correct" in quotes because we're just not good enough to hit 100%). But, just like any other tool, TDD alone is not enough for a successful project (MS findings about project failure predicted by organizational issues).

borkdude 2016-05-07T20:32:14.000329Z

@sveri: thanks for the information

sveri 2016-05-07T20:38:31.000330Z

@seancorfield: I totally agree that these findings are language agnostic. At work we do not do TDD, but we write a lot of unit tests as part of the feature work, also integration tests for these and we have two guys working in QA that do a lot of UI test automation. So our test suite is pretty extensive and we have a relatively low bug count (keeping it mostly under 10 known bugs over the last 5 years with some spikes, for a code base of several 100-thousand lines of Java code). Still, I am very certain, if we would do TDD our code would look better from a design and architectural perspective. We are slowly reaching a point now, where we fight our code base and "design decisions". For the last 5 months we tried to put a REST interface onto our web application and finished like 20% which is much less than everybody expected. Understandibly, management is not that amused about that.

sveri 2016-05-07T20:39:06.000331Z

I also sent around the findings of that paper, also to our management, but got no feedback about it, so, well, what should I say, there is only so much you can do

borkdude 2016-05-07T20:43:47.000332Z

I have the feeling that with Clojure you can at least move forward. Recently I saw a colleague struggling with some type decisions another colleague had made and it took him two or three hours to work around this

sveri 2016-05-07T20:46:51.000333Z

@borkdude: So much this. I cannot count the hours I spent fighting inheritance and strange patterns we implemented ourselves. This also includes my code of course. Decisions that seemed to be good turn out to be a desaster a few months later and then you have so much code using all these patterns already...

sveri 2016-05-07T20:47:25.000334Z

In clojure I would just add another key to my map, ding dong, ready

3
borkdude 2016-05-07T21:04:46.000335Z

@sveri: At my work we have microservices, but all common types are in one library called 'types'

borkdude 2016-05-07T21:04:57.000336Z

@sveri: This is probably a design mistake

sveri 2016-05-07T21:07:07.000337Z

@borkdude: I am sure you will find out sooner or later

borkdude 2016-05-07T21:07:39.000338Z

@sveri: I'm not sure. First I thought: this is much better than what we have in Clojure, type safety, etc. But then I saw my colleague struggle with this problem I just mentioned.

sveri 2016-05-07T21:25:59.000339Z

@borkdude: You will see him do that again and again. Code and requirements do change, so types have to do too. While it may be easy to change types, it is hard to change all the eco system that you built around these types and that make certain assumptions. Like inheritance and design patterns. The only thing where I find it superior is when I do refactoring, with java and eclipse I can even do it across projects and it works for standard cases.