2015-11-13 3 views
3

Какие шаблоны доступны для соблюдения принципа Open/Close при программировании в F #?Нужно руководствоваться принципом открытого/закрытого с F #

Например, я уверен, что соответствие шаблону внутри F # отлично подходит для некоторых сценариев. Но какое руководство существует, если вы не хотите изменять конструкцию сопоставления шаблонов каждый раз, когда новый бизнес-код предназначен для работы?

Пример:

let getFullName nickName = 
    match nickName with 
    | "Bizmonger" | "Rico" -> "Scott Nimrod" 
    | _ -> "not found" 

getFullName "Bizmonger";; 

Что происходит при введении новых случаев?

Следовательно, я не хочу изменять эту функцию.

+0

Если вы добавляете новый случай в разграниченный союз, вы должны иметь код, соответствующий этому случаю, поэтому вам нужно изменить соответствующую функцию. (Вы можете использовать отражение, чтобы избежать этого, но оно уродливое и неэффективное) – Petr

+1

Некоторые лекции [здесь] (http://stackoverflow.com/a/5578381/4925216) или [там] (http://fsharpforfunandprofit.com/) fppatterns /) – Sehnsucht

ответ

5

Я думаю, что проблема проблемы, с которой вы сталкиваетесь, называется проблемой выражения.

Функциональный код, использующий алгебраические типы данных, расположен на одной стороне, где он должен определять исходный проблемный домен и создавать и добавлять новые функции, работающие в этом домене. С другой стороны, это довольно сложно, особенно после того, как вы разработали набор функций для добавления типов в исходный домен.

Объектно-ориентированный код находится на другой стороне проблемы. После того, как вы определили свой начальный проблемный домен, становится чрезвычайно сложно добавить новые функции, потому что все типы должны быть расширены для его реализации, но относительно легко расширить область до новых проблем.

Рассмотрим

type Shape = 
    |Circle of float 
    |Square of float * float 

module Shapes = 
    let area = function 
     |Circle r -> Math.PI * r ** 2.0 
     |Square (a, b) -> a*b 

    let perimeter = function 
     |Circle r -> 2.0 * Math.PI * r 
     |Square (a, b) -> 2.0 * (a + b) 

Здесь легко добавлять функции, потому что я могу просто определить поведение для каждого типа формы, но это трудно, чтобы добавить новые формы, потому что я должен редактировать каждую функцию.

[<AbstractClass>] 
type Shape() = 
    abstract member Area : double 
    abstract member Perimeter : double 

type Circle(r) = 
    inherit Shape() 

    override this.Area = Math.PI * r **2.0 
    override this.Perimeter = 2.0 * Math.PI * r 

type Square(a, b) = 
    inherit Shape() 

    override this.Area = a*b 
    override this.Perimeter = 2.0 * (a+b) 

Использования OO, легко добавлять новые формы, но это трудно новые свойства или методы формы, потому что я должен изменить каждый тип.

Я не знаю, если вы когда-либо использовали шаблон посетителя в объектно-ориентированном программировании, но потребность в этом шаблоне возникает из-за трудности выражения структур, которые могут быть легко выражены алгебраическими типами данных в функциональном программировании.

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

4

хорошо, как вы только что узнали, в данном случае это легко добавлять новые функции (можно сказать, что оно открыто в этом отношении), но трудно добавлять новые случаи

Но, конечно, вы можете просто использовать классы/объекты/интерфейсы F # так же, как вы делаете в C#, и поэтому вы получили ваши хорошо известные модели объектно-ориентированного программирования, а также


кстати: ни в коем случае String не является хорошим выбором для реализации бизнес-кейсов ... вы выиграли 't получить OOP O/C, и вы не получите FP союзных типов лакомства таким образом

+0

Хммм ... Я бы ожидал, что для случаев было бы распространено отображение таких идентификаторов, как целые числа и строки, основанные на чтениях из базы данных. Я совершенно новичок в этом, поэтому, пожалуйста, простите меня. –

+2

уверен, но вы используете 'Strings' здесь как * ярлык для случаев * (так же, как и вы, на C#) - это не большая проблема, но обычно вы бы хотели что-то вроде' type Nicknames = Bizmonger | Рико | ... 'Конечно, пример немного беден, потому что вы просто будете использовать перечисление в любом случае, но я надеюсь, что вы получите идею. – Carsten

+0

Я еще не узнал о типах в F #. Но спасибо. –

Смежные вопросы