HN user

tommikaikkonen

137 karma
Posts9
Comments29
View on HN

I love using attrs, like the idea of bringing something similar to the standard library, but strongly disagree with the dataclasses API. It treats untyped Python as a second class citizen.

This is what I'd prefer

  from dataclasses import dataclass, field

  @dataclass
  class MyClass:
    x = field()
but it produces an error because fields need to be declared with a type annotation. This is the GvR recommended way to get around it:
  @dataclass
  class MyClass:
    x: object
You could use the typing.Any type instead of object, but then you need to import a whole typing library to use untyped dataclasses. I highly prefer the former code block.

There's a big thread discussing the issue on python-dev somewhere. Also some discussion in https://github.com/ericvsmith/dataclasses/issues/2#issuecomm...

Anyway, it's not a huge issue—attrs is great and there's no reason not to use it instead for untyped Python.

I think that's natural and OK. I would compare writing my thesis to writing my first full application after learning how to read and write code—even after several iterations under a skilled supervisor, the codebase is still going to have a more or less fledgling and awkward quality to it, even if the functionality proves useful. The second attempt takes less effort and results in higher quality output.

Similar to how few people would put their first application out in public, I prefer to keep my thesis private unless someone finds the information really useful :)

Thanks. The thesis is really mediocre academically, so I don't feel comfortable putting it out in the public, but if you leave an email address here or contact me through Twitter I'll gladly send it to you.

Agreed. I think this kind of research can give ideas on what kind of experiments to run on pricing pages, but there are so many factors affecting real life plan choice that everyone should have their own A/B testing setup to see what works for them specifically.

I did my MSc thesis on SaaS pricing pages. I'll share what I found, since I think many people in this thread may find it useful.

I tested how Mechanical Turkers (N=~400) chose plans on pricing pages with 4-tiered subscriptions plans, for both a file sharing service and a payroll software service. Each respondent was randomly assigned to one of 4 conditions, where the presented pricing page was slightly different. The scenario was framed as choosing a SaaS plan for a company they're employed at.

The first variable I varied was plan order. Half the respondents saw a pricing page with plans in increasing price order (cheapest first), the other half in decreasing price order (most expensive first). There was a statistically significant difference between the plan choices for these groups; respondents in the most expensive plan first condition chose a more expensive plan. This phenomenon has been seen before outside SaaS, and it's called the price order effect.

Another variable I tested was exchanging the cheapest ($5) plan for a free plan. Half the respondents saw a free plan, the other half a $5 plan. There was no statistically significant difference in the plan choice for these groups.

Getting familiar with previous literature, I would surface a couple of general thoughts:

- The most expensive plan first approach may give the visitor a more expensive image of the product, a higher "reference price". If a prospective customer is comparing two products from two different companies, they may favor the one that seems cheaper (has a lower "reference price") even if the offerings may provide similar value.

- The hypothesized mechanism for the price order effect is that you don't look at all the options as a whole, but you begin by assessing the first option, which is the leftmost one for us reading left-to-right, and then judge the next option by comparing it to the previous one, and so on. You compare added (more features/less cost) and lost (less features/more cost) value. Because we weigh losses heavier than benefits, there's an inertia toward the initial options. Only options with benefits that greatly outweigh losses combat that inertia. Hence respondents tended to choose plans more on the left.

I've migrated a lot of code from moment to date-fns because of moment's bulky size and vast, mutable API. Luxon seems to fix the API issue. date-fns is still great for simple operations, but I'll definitely consider this for new projects with nontrivial datetime handling.

I agree, that doesn't look bad. However, this type definition forces you to supply one argument per function call, which looks awful in JavaScript:

    fn(1)(2)(3)
That's a big drawback for me. Libraries like Ramda allow one or more arguments per function call:
    fn(1, 2, 3) === fn(1, 2)(3) === fn(1)(2, 3)
That's what makes the verbosity unbearable, as each type of call needs its own type.

Currying in JavaScript is really nice if you can remember the arities of each curried function you're using. If you forget to call up to the last argument, you'll be passing a curried function instead of the expected value, and it can throw an error really far away from the bug. And instead of normal data to inspect at the error site to point you to the bad call, you'll only have a generic function name to look at. I've spent more hours than I'd like to admit debugging these situations.

A type system would detect these cases, but TypeScript and Flow don't have great support for curried functions. Typing them is very verbose.

Hypothesis has been highly useful in the team I work in. It is also one of the most robust property-based testing library in any language. Thanks to the project contributors and Stripe for investing resources in making it even better!

Property-based testing has made testing more productive and fun for me. You write a few lines of code that produce a large amount of tests. The idea is obviously so useful, I'm surprised it's uncommon in practice. When you think about coverage in terms of inputs applied instead of statements executed, property-based testing is far more productive than writing tests by hand.

It's not a silver bullet though. Some property-based tests are easy to write but offer little value. Sometimes you spend more time writing code to generate the correct inputs than the value of the test warrants. It has a learning curve. Still, I think it is the most powerful tool you can master for testing.

I've applied the Monoid and Semigroup patterns often in Python and JS. Knowing about CT helps you leverage their properties (associativity, often commutativity, having an explicit identity element for a monoidal operation), and writing tests against those properties.

They're common patterns a lot of people use without knowing anything about CT, for example if you fold/reduce over a collection with an initial value, and the collection may be empty, you're looking at a monoidal operation. You can call the initial value a constant identity. Like sum, product.

If you fold/reduce over a collection where the collection may not be empty, and you need to use the first element as the initial value, you're looking at a semigroup operation. Like min/max/mean.

Implementing a find function makes this read a lot nicer. You could also call it find_first or find_next.

    def find(predicate, iterable, default=None):
        """Returns the first value that matches predicate, otherwise default=None"""
        return next(
            (x for x in iterable if predicate(x)),
            default
        )
Which turns the expression to
    find(lambda x: 'widgets' in x, mixed_widgets)['widgets']

While it's far from a functional language, I find that it's possible to build functional style abstractions without too much headache. The iterator protocol is so well supported by the language and the standard libraries that using map, filter, itertools, generator expressions & comprehensions gets you a long way. You get the rest of the way by writing any specialized combinators you need and then imperative code to tie things together. You can build up a lazy pipeline of data transformations that works pretty well.

There are some gotchas where you need to explicitly copy (itertools.tee) iterators when you have multiple consumers, and be careful with mutable values, but it's manageable.

It would be nice to use curried functions as functools.partial gets verbose, but at that point you're far from Pythonic code.

I haven't read the book OP linked, but I've been going through Haskell Programming from First Principles for the last 6 weeks or so and it's been fantastic. The price tag is well worth it in terms of frustration and time saved. I'm about two thirds done.

I really like that it builds up from the basics, starting from lambda calculus, and is also very complete in explaining every concept. I don't feel like anything is left unexplained. This is important, because coming from dynamically typed imperative languages, a lot of concepts in Haskell are so alien that you feel like you're learning programming all over again.

The exercises set it apart from other resources. They're plentiful, start simple, but quickly increase in difficulty. A lot of times I thought I had a concept mastered until the exercises presented gaps in my knowledge -- which made me learn the concept that much better.

The completeness means it's a long book (currently 1233 pages). You'll probably need a healthy dose of existing motivation to learn Haskell to get through it.

Author of that repo here, I'm glad you found it useful! I've used that template as a starting template for purely personal projects, so beware: it does not have the polish of a well-maintained django package. But it's been convenient for getting new projects running up quickly on Heroku and S3.

If you decide to use it, you might want to look at the development of the original Django Twoscoops Project (https://github.com/twoscoops/django-twoscoops-project) during the last year or so, as they haven't been pulled in to my repo.

It seems like you're only seeing the aesthetic side of design and missing the functional side. For example interface patterns, typography and color palettes can be evaluated without opinion.

Interface patterns have their best use cases and the designer needs to pick the right one for each part of the design, making sure it works as a whole.

Typography is based on making text easily readable - there's always some leeway for opinionated typography but a designer shouldn't stray far from best practices.

While the exact colors in a palette can be opinionated, they too have characteristics that should be assessed without opinion. Are there enough contrast between the colours? What if the user is colorblind? Will people with low vision be able to see everything clearly, especially text? Are the colors appropriate for their intended use, for example a red hue for alert, green for success)?

"It does not look right" and "it does not work" are the kind of feedback you get from people who don't know the inner logics of a design. Feedback from an experienced designer might not mention aesthetics at all.

You can't not communicate with a typeface - they always have a certain feel, which is why there's a whole lot of them. Typefaces also have characteristics that make them more suitable for certain situations. For example, Georgia is designed for the screen with a tall x-height but Garamond looks better in print with its small x-height. Then there's condensed fonts, small caps.. It's certainly hard for a non-designer to catch all the visual differences but I believe they are sensed subconsciously by all.

I agree. Many of the transitions in the demo presentations, while fancy, take too long to finish. They don't add anything to the presentation.

If you're going to use effects, make sure they actually contribute to or complement the content.

The measures you can try with the buttons (40, 65 and 90) are to see how the text looks on the edges of these guidelines (which I've written as 50-80 characters).

It's not a scientific number by any means, rather a general "consensus" derived from all the typography literature and articles I've read. The measure is not as simple as it seems, though; Readers seem to prefer a shorter measure while reading speed is actually increased with a longer measure, like shown in this study:

http://psychology.wichita.edu/surl/usabilitynews/72/LineLeng...

Author here, thank's for pointing that out. I just put my blog online yesterday morning, and this was an article that I had written back in the summer in HTML markup. Seems like there were some conversion errors to Markdown that I didn't notice.

Erroneous: Research shows that consumers with a utilitarian motivation find a low-arousal environment more pleasuraigh-arousal one.

Fixed: Research shows that consumers with a utilitarian motivation find a low-arousal environment more pleasurable than a high-arousal one.