Hi Francesco!

Some comments inline.

> Using Ecto and changesets to validate the state of the struct does the
job in a way, but it does not ensure the struct is valid "at any time",
which is what I'd like to achieve instead.

There are no guards, type system, or any other mechanism that can actually
guarantee this is true generally. If you are talking about DDD, then we are
talking about business rules and those may get quite complex. The best we
could do is to guarantee that the struct has certain types in certain
fields, but it does not necessarily say the struct *is valid*.

And even if you say, "just checking the types are fine", then we can't
provide that without a full-blown type system.

>From the original proposal, what makes the most sense is to restrict which
modules can create and/or access structs fields so there is at least an
implicit guarantee that everyone is going through an existing, pre-defined
API. But even if we do add those checks, they can be easily bypassed by
doing something as simple as:

def bad(user) do

  %{user | name: 5}

end


I understand the counter-argument is "some check is better than no check"
but a check that is part of the language has to provide better guarantees
than this. Perhaps someone can do a Credo check that guarantees a struct
can only be accessed in the module that defines it and that should cover
most of the cases.

*José Valim*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D


On Thu, May 30, 2019 at 7:35 PM Francesco Lo Franco <
[email protected]> wrote:

> Yes, that's the approach I took, in fact. The issue with this approach are:
>
> 1. have to use a library to do what, I think, should be provided by the
> core language (that's my personal opinion)
> 2. it still does not enforce in any way invariants. I can still do
> invalid_struct = %MyStruct{} or %MyStruct{name: 5} even if the field in the
> embedded schema is defined as :string
>
> Using Ecto and changesets to validate the state of the struct does the job
> in a way, but it does not ensure the struct is valid "at any time", which
> is what I'd like to achieve instead.
>
> On Thursday, 30 May 2019 18:29:19 UTC+1, Allen Madsen wrote:
>>
>> You're probably better off using an ecto schema and changeset.
>>
>> Allen Madsen
>> http://www.allenmadsen.com
>>
>>
>> On Thu, May 30, 2019 at 10:27 AM Francesco Lo Franco <
>> [email protected]> wrote:
>>
>>> Sorry to dig up this very old post, but I thought I wanted to just +1
>>> this proposed feature because I reckon it will be extremely useful for a
>>> language such Elixir, which, besides, sees DDD being applied much more than
>>> in the past. Is there any update or news about this? I'd be happy to know
>>> more or contribute to this if helpful.
>>>
>>> On Monday, 6 November 2017 16:50:18 UTC, Rafał Radziszewski wrote:
>>>>
>>>> Hi,
>>>> since I see a lot of potential in the feature I'd like to provide a
>>>> couple of arguments in favour of it. I will use points for ease of
>>>> discussion.
>>>>
>>>> 1. I am not going to talk about specific implementation (through @guard
>>>> property) as proposed, but generally about giving possibility to create
>>>> invariants in structs, i.e. possibility to raise on instantiating struct
>>>> with invalid data.
>>>> 2. No solution will be perfect (i.e. mentioned possibility of using
>>>> Map.put/3 or manually creating struct as map through %{__struct__:
>>>> MyStruct}, using those features is somehow similar to addressing raw memory
>>>> in C - if you're doing it, you should expect problems), a lot can be
>>>> achieved by modifying just struct/2, %MyStruct{} and %MyStruct{my_struct |
>>>> key: val}, as those are prevalent in the codebase.
>>>> 3. Though there is possibility to define function performing those
>>>> validations (i.e. it is quite common to see new/1 in a lot of libraries),
>>>> there is no way to restrict creation of struct to that functions. I believe
>>>> it to be a good decision, since data is just data, but it makes it quite
>>>> easy to make a mistake that is hard to pin down, since no warnings or any
>>>> other suggestions are issued.
>>>> 4. While it is correct that in general forcing users to use API is the
>>>> way to go, literal struct creation is very common and in most cases
>>>> correct, which can lead to confusion. It can also encourage extensive
>>>> boilerplating of functions like 'new', just in case, which can be
>>>> detrimental to language clarity.
>>>> 5. Adding invariants does not breaks the premise of validating data on
>>>> boundries, it supports it. Ability to restrict field values leads to
>>>> cleaner code, since it is not necessary to check input validity in every
>>>> function. Raising error on invalid instantiation actually forces to perform
>>>> validation on the boundry - in the place where struct is instantiated. It
>>>> allows for less defensive coding, since programmer can actually assume that
>>>> struct is correct.
>>>> 6. Matching on %Foo{} in this scenario doesn't actually cause problems,
>>>> since the structure won't be even instantiated if it is wrong, unless it's
>>>> manually put  together from map.
>>>>
>>>> In general I believe that adding more possibilities to express ideas
>>>> through types could really help the language.
>>>>
>>>> Cheers,
>>>> Rafal
>>>>
>>>>
>>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/895a5599-2f91-4abf-aeef-81adcfdffc2d%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/895a5599-2f91-4abf-aeef-81adcfdffc2d%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/db5da3be-0e85-4bb8-9291-926c505fdd81%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/db5da3be-0e85-4bb8-9291-926c505fdd81%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JrF-7Gb6NNJ1%3DVt7mcP8Yyu%3DsTnvC2xsf0_kO7jaZ%3DBg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to