Alexey's profileLife vs. ProgrammingPhotosBlogListsMore Tools Help

Blog


    March 24

    Российская обувь в Бельгии

    Сегодня, гуляя по городу, встретили на "развале" коробки с обувью российской марки "Ральф Рингер". На коробках даже надписи сделаны по-русски.

    Помимо самого факта удивило две вещи:

    1) Цена. Пара ботинок стоила 20 евро.
    2) Качество. Какими-то топорными они мне показались. Особенно внутри.

    Поскольку я носил обувь от "Ральфа" и знаю, что она из себя представляет (и сколько стоит), то могу допустить, что здесь продавались подделки. В этом смысле ситуация становится еще более интересной: тут ведь практически нет подделок (хотя это в магазинах, на развалах, вероятно, полно) и подделывают обычно престижные фирмы типа Экко и т.д... А подделка обуви российского производителя, причем даже с коробками на русском языке выглядит странной :)

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

    Но цена в 20 евро все равно удивляет.

    March 14

    О кочевниках

    Только что посмотрел фильм "Кочевник".
    Однако, как человек, закончивший школу в Казахстане и обрывками помнящий плохо выученную историю этого самого Казахстана, засомневался в могуществе хана всея Казахстана. Ибо, насколько я помню, от войн Казахстан спасался присоединением к Российской империи, причем по кусочкам, "пожусово" (жус - племя, их было три в Казахстане: старший, средний и младший).

    Однако это все ерунда. Когда мы заспорили с женой и полезли искать факты в интернете, то оказалось, что то, что я всю жизнь знал под названием "кызыл-орда", оказывается, называется в России "золотая орда" и преподается в российских (по крайней мере в подмосковных) школах под этим названием :)

    Прикольно. Видимо, "кызыл" - это "золото" по-казахски. Столько лет прошло, а я продолжаю "изучать" казахский язык, по которому у меня тройка в аттестате. Да и то благодаря состраданию учительницы, ибо молчал на экзамене как партизан.... :)

    WebServices: что может быть проще?

    В последнее время ничего не пишу - сижу, ковыряюсь с WPF. Нравится очень, гибкость офигительная, но многое нужно постигать как бы сначала... Впрочем, об этом в другой раз, а пока вернусь к веб-сервисам.

    Писать этот постинг меня сподвигло то, что сразу с двумя человеками из разных компаний и разных городов недавно разговаривал о том, как (и почему именно так) нужно строить архитектуру при работе с веб-сервисами.
    Поскольку сейчас я как раз занят тем, что пишу одновременно и слой веб-сервисов и клиента  к нему (с использованием того самого WPF), то об этом я и расскажу. Заодно прерву "затяжное молчание".

    Итак, начнем есть трехслойный пирог (серверная логика, веб-сервисы, клиентская логика) с середины, то есть, со слоя веб-сервисов.

    Создавая слой веб-сервисов мы создаем контракт между двумя остальными частями (серверной и клиентской). Сам же слой представляет собой набор доступных операций, этакий API, для слоя клиентской логики и является не более, чем клиентом для слоя логики серверной.
    Подчеркну важный момент: в этой схеме "клиент" ничего не обязан знать о том, как там устроена серверная часть, какими данными она оперирует, в каком виде все это хранит и т.д. Клиентский слой логики "мыслит" совсем другими категориями, у него совершенно другие задачи и, быть может, даже другая бизнес-модель.

    Отсюда вытекает простая рекомендация: не нужно передавать клиентскому приложению объекты бизнес-модели серверной логики. С точки зрения развития и поддержки приложения, я бы даже сказал "никогда не нужно".

    Создавайте отдельные объекты для передачи посредством веб-сервисов. Такие объекты называются "контрактами данных" (Data Contracts).
    Ваш слой веб-сервисов будет оперировать объектами бизнес-логики серверной части, но для передачи клиенту будет "транслировать" их и их данные в объекты-контракты данных и лишь затем передавать.

    Зачем это нужно? Очень просто. Как я уже сказал, клиентское приложение, пользуясь веб-сервисом Reports, совершенно не заинтересовано "знать" бизнес-модель серверной части. И для него бизнес-сущность "User" вовсе не является набором "запись в таблицу Users + ссылка в таблицу Occupations + ссылка в таблицу Departments + 2 ссылки в таблицу Addresses по их IDшникам". Ему и надо-то воспользоваться сервисом Reports всего лишь для того, чтобы этот самый репорт отобразить, и для него User - это "монолитный" объект со всеми необходимыми адресами, должностями и т.д. А вот информация о паролях, логинах, ролях и т.д. ему совершенно не нужна, поэтому и передавать ее в сервисе Reports не за чем.
    Поэтому слой веб-сервисов "берет" все эти серверные бизнес-объекты (адреса, должности), трансформирует эти данные в отдельный объект, определенный контрактом, и уже его передает клиенту.
    Кроме этого, контракты данных получаются достаточно простыми и четкими, что позволяет легко использовать сервисы даже из не-.net приложений, если придется. Да и в любом случае удобнее, чем передавать сложные объекты бизнес-модели, часто имеющие свою иерархию, избыточную с т.з. веб-метода информацию и т.д.
    Все счастливы.

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

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

    Кстати, еще о клиентской части.
    Здесь я тоже предложил бы не использовать в приложении объекты (контракты данных), полученные от веб-сервиса.
    Вместо этого часто лучше трансформировать данные из этих контрактов в бизнес-объекты клиентской модели.
    Плюса здесь два, и оба существенные.

    Первый: Вы получаете для работы "нормальные" бизнес-объекты, наделенные необходимым поведением, необходимыми свойствами, нужными для работы клиентской части приложения и т.д. Это гораздо лучше, легче, да и правильнее с точки зрения ООП, работать с объектами бизнес-модели, нежели с "безликими" наборами данных, которые вы будете пихать по очереди в немереную кучу классов-обработчиков, которые будут как-то манипулировать этими данными. В небольших (по функциональности и времени поддержки) приложениях это еще куда ни шло, но в случае серьезных проектов вы рискуете если не потерять контроль над сложностью системы, то наплодить кучу лишних обходных путей (представьте себе судьбу того, кому в этих "заплатках" потом разбираться), вместо того, чтобы продолжать работать в рамках объектно-ориентированной парадигмы.

    Второй: Вы сами контролируете объекты, с которыми вы работаете.
    После получения данных от веб-сервиса и трансформации их в собственные объекты клиентской бизнес-модели, программисты оной могут творить с/из этих объектов свободно что угодно.
    Нужно сделать Undo? Пожалуйста, добавили необходимые методы. Нужно, чтобы объект оповещал об изменении его свойств? Пожалуйста, реализовали INotifyPropertyChanged и получили беспроблемный двусторонний байндинг в UI. Нужна собственная иерархия? Опять пожалуйста, хозяин-барин.

    Итак, коротко обобщим основные рекомендации:

    1. Создавайте на стороне серверной логики полноценные объекты бизнес-модели и работайте с ними (а не с именованными наборами данных, за поведение которых отвечают сторонние классы, которые хрен найдешь, если не знаешь).
    2. Создавайте контракты сервисов (API, наборы операций, веб-методы), которые передают и принимают контракты данных (простые типы-носители необходимых для операции данных). Никогда не используйте бизнес-объекты серверной логики в качестве контрактов данных.
    3. Не работайте напрямую с объектами-контрактами данных в клиентском приложении. Создайте полноценные объекты бизнес-модели клиентской части, и заполняйте их данными, полученными от веб-сервисов. Так вы одновременно получите возможность развивать и управлять этой моделью и избавитесь от необходимости реализовывать странные сторонние классы, отвечающие за манипуляцию данными (те самые, которые потом хрен найдешь и проконтроллируешь).

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

    Пример (упрощенный) веб-метода, возвращающего данные о производителе товара:

    public DataTypes.Brand GetByID(int id)
    {
        BusinessLogic.ManufacturerGetById action = new BusinessLogic.ManufacturerGetById();
        BusinessEntities.Manufacturer m = action.Execute(id);
        return Translators.BrandToManufacturerTranslator.Translate(m);
    }

    Здесь ManufacturerGetById - это класс-action, умеющий вернуть сложный объект бизнес-модели серверной части по его идентификатору. Далее он трансформируется в простой объект контракта данных Brand, который и будет предоставлен клиенту.

    Клиент же, получив эти данные, таким же способом заполняет ими свой объект
    Brand : Company, INotifyPropertyChanged, ISearcheable
    с которым и продолжает работать дальше.