рефакторинг 2 тесно связанных методов - PullRequest
0 голосов
/ 16 мая 2011

Хорошо, я делаю макет распределенной системы.каждый экземпляр mClass (объекта) используется 1 потоком.Изменяемые данные не могут быть переданы между объектами mClass. Это пример кода, аналогичного тому, что у меня есть:

type mClass (mID:id)=
    member this.ID=mID

    let resolve : id->mClass  =... //This function turns IDs into the objects they represnt
    ...
    let managementInfo = ref Some mutableData

    //this should only ever be called by the GiveControl method.
    private member this.TakeControl (frozenData) =
        let defrostedData = ... //a variable that works out the unfrozen version of the frozenData
        managementInfo := Some defrostedData


    ///This is a helper that ensure that when ever someone else is told to take control 
    ///that all my internal data and any functions i need to call to tell others are done
    ///And convert the data a nonmutable form 
    ///(Mutable data can not be tranfered between different instances of of mClass (objects), 
    ///as this is a mockup of a distributed system, where the instances of mClass can't
    ///@param: nID this ID of the object we are giving control to
    ///@param: callbacks: a list of functions to call to tell other objects i've given control 
    private member this.GiveControl nID (callbacks: list<id->unit>) =
        let updateInternalData = ... //A function to upate my internal state
        updateInternalData;
        ignore (List.map (fun f-> f nID) callbacks);
        let freezeData data= ... //a function make our mutableData into nonmutable data
        let frozenData = (!managemenInfo).Value|>freezeData 
        managemenInfo:=None;
        (nID|>resolve).TakeControl (frozenData)

    ...

закрытый член this.GiveControl был первоначально объявлен: let giveControl, но это заставило компилятор жаловаться на ошибку- объявление нового типа, пока я не изменил его на частный метод.

Вопрос в том, как я могу переформулировать этот код, чтобы объединить два метода в один.(или, по крайней мере, заставьте GiveControl вызываться только изнутри этого объекта (как бы настоящего частного), а TakeControl вызываться только из GiveControl)

Ответы [ 2 ]

0 голосов
/ 17 мая 2011

Как вы сказали, у вас изначально был дан в качестве элемента letControl. вещи, которые делаются с помощью let, являются истинно частными ценностями. к ним нельзя получить доступ снаружи вашего объекта.

Это требование к классам в F #, которое позволяет делиться перед членами. также F # не единственная пасха для методов класса, таким образом, ваш let может ссылаться на любой метод, который вам нужен.

тип mClass (mID: id) = член this.ID = mID

let resolve : id->mClass  =... //This function turns IDs into the objects they represnt
...
let managementInfo = ref Some mutableData
let giveControl nID (callbacks: list<id->unit>) =
...

private member this.TakeControl (frozenData) =
    ...

Это не решит вашу вторую проблему, однако

0 голосов
/ 16 мая 2011

Зачем вам нужно защищать себя от себя?Даже в этой версии происходит изменение состояния другого mClass (вы вызываете TakeControl из потока подачи, а не из потока получения).Возможно, вместо того, чтобы беспокоиться о передаче изменяемой информации, вы должны использовать систему передачи сообщений и быть в здравом уме относительно использования информации (т. Е. Нулевых ссылок после передачи).

Если вы действительно хотите внутренний доступ к чему-либо, то привязка let являетсяпутьВы можете переместить эти методы управления в отдельный класс и позволить создавать каждый экземпляр для mClass (или параметра).Однако нет никакой гарантии гарантировать, что последняя часть о том, что TakeControl может вызываться из GiveControl, если вы как-то не перекладываете ответственность за выдачу и получение на принимающую сторону.

...