вторник, 23 июля 2013 г.

Записки программиста #2. Портативные библиотеки классов или совместное использование кода в различных проектах.

Разрабатывая приложения для Windows Phone 8 и Windows 8 часто встает вопрос, как сделать так, чтобы написанный один раз код, работал везде, хоть они и основаны на одном и том же ядре Windows 8 и Microsoft пытается всячески сократить разрыв между ними, но различий довольно много. А если встает вопрос о поддержке проекта на IOS и Android по средствам Mono, то порой хочется плакать… Ведь в самом худшем сценарии, придется поддерживать как минимум 4 проекта и изменение в одном, несут большое количество изменений в другом, те большое количество ручного труда. Именно такой и встал у меня вопрос в начале разработке, ведь об этом стоит подумать заранее. До этого я с этим сталкивался только вскользь.
В целом, для решения этого рода задач, существует два метода:
Портативный библиотек классов
Совместное использование кода

Портативный библиотек классов
Одна из ключевых частей взаимодействия между платформами является концепция портативной библиотеки классов (или PCL). Портативная библиотека классов является компонентом, который можно добавлять в обе платформы, но к сожалению, не все можно уместить туда.
Туда можно написать различную бизнес логику, но к сожалению, как пример, туда нельзя написать код доступа к файловой системе, та обе платформы имеют различный API. В целом все не плохо, но чем больше кода Вы пишите, тем больше возникает такого рода проблем. Так же не стоит забывать, что визуальное представление отнимает также большое количество времени.
Что же такое PCL, хорошо показано на рисунке:

А если добавит Xbox получите что-то вроде этого:

Как вы уже поняли, чем больше целевых платформ, тем меньше вы получаете доступа к API. Для решения этой проблемы используются интерфейсы, которые будут реализованы уже на каждой платформе в отдельности.
В таблице ниже дается обзор того, что поддерживается в PCL:

Feature
.NET Framework
Windows Store
Silverlight
Windows Phone
Xbox 360
Core BCL
Да
Да
Да
Да
Да
Core XML
Да
Да
Да
Да
Да
Core WCF
Да
Да
Да
Да

Core networking
Да
Да
Да
Да

XML Serialization
Да
Да
Да
Да

JSON serialization
Да
Да
Да
Да

Datacontract serialization
Да
Да
Да
Да

IQueryable
Да
Да
Да
7.5  и выше

dynamic keyword
4.5
Да
Да


View Models
4.5
Да
Да
Да

Data Annotations
4.03 и выше
Да
Да
Да

LINQ
Да
Да
Да
Да

XLINQ
4.0.3  и выше
Да
Да
Да
Да
MEF
Да
Да
Да


System.Numerics
Да
Да
Да


Совместное использование кода
Другая форма повторного использования через единый исходный код.  Для того чтобы сделать это, Вы должны добавить существующий файл с исходным кодом в качестве ссылки. Это позволит добавить файл в проект, но сам файл все еще живет внутри каталога с исходным проектом.  Если вы обновите его, то она будет изменен в обеих библиотеках. 
Используя данный подход Вы все еще ограниченны общим API библиотек. Так как исходный файл должен работать в нескольких проектах.  Однако, существует еще один метод, который можно использовать, чтобы обойти это: директивы препроцессора.

Когда использовать первый способ, а когда второй?
Я бы рекомендовал использовать PCL в небольших проектах, где идет большое количество одинакового кода минимально привязанного к платформе. Как правило это бизнес приложения для Windows 8 и Windows Phone7/8 где интерфейсами заменяются критические части и реализовываются для каждой платформы отдельно, как я писал выше.
Если Ваш код одинаковый для обеих платформ, но PCL не поддерживает его.  Это случается иногда, когда оба API живут в разных пространствах имен. То проще всего использовать директивы препроцессора, чтобы преодолеть это.
Но когда код пишется под разные платформы и очень часто поведение многих частей отличается для каждой платформы, я бы советовал использовать смесь этих двух подходов. Суть этого заключается в следующем, пишется ядро кода в PCL, создаются проекты для каждой платформы и наполняются ссылками на код из PCL и уже потом как надстройка используются директивы препроцессора. Пока данных подход в моем новом проекте меня радует. Единственное, не гонитесь сразу за многими платформами, поддерживайте одну, а лишь потом переносите код на другие. Объясню почему, когда Вы только начинаете писать код, Вы создаете большое количество новых классов, что-то удаляете, что-то меняете и как следствие Все их нужно переносить в другие проекты, если их 4 + библиотека PCL где все изменения, то это увеличит время разработки и создаст некоторый дискомфорт. Но как не крутите это намного лучше, чем 4 независимых проекта.