Pull to refresh
3
0
Дмитрий Колодько @prowwid

Lead Software Developer

Send message
Здравстувйте Pyrus,

Представьте, вдруг она перестала работать — а вам даже позвонить некуда…

По такой логике AWS, Azure, Digital Ocean и любым другим поставщикам облачных услуг доверять вовсе нельзя, а надо строить свои дата-центры. Но согласитель — это ведь довольно накладно и очень редко, когда оправдано.

Я с Вами не спорю, такая вероятность естественно есть. И от отказа облачного сервиса всегда надо себя обезопасить.

Вы не думали над вариантом использования облачной распределенной базы (Cosmos DB или альтернатив) с репликацией в свою собственную(в которую не сложно перенести данные из облачной, к примеру для Cosmos DB кажется наиболее близка ArangoDB) на случай экстренного восстановления?

К примеру иметь несколько серверов для репликации, которые будут использоваться в случает отказа основной базы и писать в них чем-то вроде сервисов на Go срабатывающих на CRUD операции.

Если не совсем понятно что я пытаюсь описать — могу визуализировать.
Утверждение что Написание тестов значительно увеличивает время разработки справедливо в первую очередь если UnitTest пишется на объекты низкого уровня.
Если разработчик не парится по поводу размера юнита, а пишет тесты исходя из здравого смысла, то возможно даже и сокращает.

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

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

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

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

Без теста мы можем вводить данные на форму, отправлять ее и смотреть что получим(может еще и дебажить в то же время).

С тестом мы просто введем нужные нам данные при написании теста и будем его запускать каждый раз когда хоти проверить правки.

От одного только сокращения времени на перезагруке страницы, вводде данных и ожидании ответа сервера можно выиграть не мало времени.

P.S. не подумайте, что я с Вами спорю — наоборот, поддерживаю Ваше высказывание
пишет тесты исходя из здравого смысла, то возможно даже и сокращает.
добавлю важный момент — юнит тесты должны быть максимально независимы от окружения.

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

Самый типичный пример — тестирование ActiveRecord моделей унаследованных от базового ActiveRecord. Тест как-бы будет проверять один класс, но по факту мы будет тестировать заодно и кучу компонетнов ORM.

Если не совсем понятно к чему я клоню, могу привести примеры кодом.
Здравствуйте Pyrus,

Вы написали, что отказались от облачных решений, но не рассматривали ли Вы перед отказом Azure Cosmos DB?
Она очень заинтересовала, но информации о ней (кроме как от Microsoft) не так то и много.

Буду благодарен если поделитесь своими соображениями, если рассматривали ее.
думаю можно и так сказать.

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

Но реалии таковы, что во многих фирмах фреймворк выбран за разработчиков и хочешь не хочешь, а берешь то, что решили за тебя.
То же и с подходами.

К примеру, фирма конвеером клепает простенькие заказы на Yii2 и вдруг заходит что-то серьезное. Скорее всего начнут делать как для конвеера и наберут кучу проблем т.к. надо было отказаться сразу от Yii2, а скорее всего и от PHP. (это так, пример из пальца чтобы передать суть)
согласен.

Все действительно упирается в варианты использования и то, что хорошо в одном случае, может быть совершенно не применимо в другом.

Насчет Name как value object с одним стандартным преобразование в строку, да это хороший вариант, для некоторых случаев избыточен но если говорить обобщенно, то я был бы рад иметь Name, Date, Status и т.п. как VO по умолчанию.

Огорчает только то, что далеко не все фраемворки (в частности ORM) дают возможности для удобной работы с VO и далеко не во всех ОО языках VO распространены и нормально поддерживатся.
добавлю к коментарию pankraty

представим что есть Junior или Middle разработчик. Ему дают задачу и он ее рализует основываясь на подходах принятых в текущем framework'е. Потом идет следующая задача, за ней следующая и в какой-то момент приложение разрастается, а подходы продолжают применяться как для более простого варианта и со временем все скатывается в помойку.

Разработчик делает вывод, что виноват framework.

В статье нет ссылки, так что вот, добавлю ссылку на пост о IOHIDeous на случай если кто пропустил
VolCh я с вами согласен.

Действителльно припекает зачастую тем, кто получает в подарок ведро лапши.

Но добавлю, что порой даже те, кто начал варить лапшу, понимают что они наделали, но винят в этом ActiveRecord, framework и т.п. (сам грешен — так делал в прошлом)

А насчет Вашего описания проблемы с использованием ActiveRecord — я об этом и думал, но не расписал более детально как Вы.
VolCh Вы естественно правы — я обобщенно говорил.

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

Для примера и привел ActiveRecord т.к. с ним очень часто допускают ошибки и, как Вы и сказали, начинают делать лапшу из бизнес и логики хранения. В итоге получаются классы на 1500 — 4000 тысячи строк где код на все случаи жизни с переплетением бизнес правил и логики ОРМ.
Для описанных случаев я бы ни VO ни хелпер не использховал.

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

Давайте разделим простые примеры и более сложные.

За простой пример давайте возьмем ситуацию, когда Person у нас не интернализируется, в отчетах не учавствует и собственоо правила форматирования имени у него всегда одни. Для такого случая, я думаю применение обычного свойства было бы уже достаточно:
public class Person
{
    private string firstName;
    private string lastName;
   
    public Person(string first, string last)
    {
        firstName = first;
        lastName = last;
    }

    public string Name => $"{firstName} {lastName}";   
}

Другое дело, если, к примеру, нам нужно будет показывать имя Person на сайте и в отчете, применяя разные методы форматирования.
Тогда можно обратиться к адаптерам/моделям отображения или т.п., но никак не к VO и не добавлять логику для отображения и форматирования для каждого места использования в сущность. Получится что-то наподобие:
public class Person
{
    public string FirstName 
    { get; set; }
    public string LastName 
    { get; set; }
   
    public Person(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }
}

public class WebPerson
{
    private Person person;
   
    public Person(Person personEntity)
    {
        person = personEntity;
    }

    public string Name => $"{personEntity.FirstName} {personEntity.LastName}";   
}

public class ReportPerson
{
    private Person person;
   
    public Person(Person personEntity)
    {
        person = personEntity;
    }

    public string Name => $"First Name: {personEntity.FirstName} | Last Name: {personEntity.LastName}";     
}


А если добавится интернализация, что-то наподобие:

public class InternationalPerson
{
    private Person person;
   
    public Person(Person personEntity)
    {
        person = personEntity;
    }

    public string Name => PersonNameFormatter.format(person);     
}


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

Я хочу сказать, что операции над данными сущности не обязательно должны быть в самом классе сущности но это и не значит, что их все надо выносить в сервисные классы.
Как уже сказал VolCh, сущности не должны отвечать за свое отображение.
В сущности должен находиться код, который работает с данными сущности в рамках бизнес логики.
К примеру, подобные методы вполне могут быть в сущности или VO сущности:
person.isActive();
person.Status.IsActive();
person.Activate();
person.IsAdult()


Надеюсь мой посыл понятен. Если нет, я приведу примеры получше.
Я с Вами не соглашусь.
Классическое ООП = «Rich Data Model» = антипаттерн.

Это заявление выглядит как типичное «ваше ООП отстой, а вот ФП — это круто».

Говнокодище пишут и на ООП языках и на ФП — проблема, в основном, в людях, а не в ООП или ФП.

К примеру, люди берут типичный MVC framework для Enterprise системы, засовывают всю бизнес логику в AcctiveRecord, а потом мы видим тысячи гневных отзывов о AcctiveRecord.
Но в то же время тысячи людей используют типичный MVC framework с AcctiveRecord для небольших систем и вполне себе счастливы, а заказчик получает новый фичи по рассписанию.

Так вот, не в AcctiveRecord проблема у первых, а в них самих. Каждый шаблон, методология и язык применимы для решения определенного ряда задач и если попытаться выйти за рамки применения то сразу начнутся проблемы.
Я Вас прекрассно понимаю.

Но в этих новостях есть и хорошие стороны — мы теперь знаем о проблемах и можем себя обезопасить или хотябы подготовиться.

Главное, чтобы «как год начнешь, так его и проведешь» не сработало для IT.
Возможно данная книга сыграла важную роль в популяризации «паттернов». Сложно сейчас рассуждать об этом.
Но во когда смешивают «паттерны» и «шаблоны» в одном контексте — вот это я считаю плохим тоном.
Я предпочитаю использовать или английский термин или перевод, но не все вместе — считаю что от этого получается какая-то каша.
Посмею заявить, что не С++ программисты не имеют ничего против слов «шаблон» и «анти-шаблон».

Абсолютно соглашусь, что паттерн и антипаттерн стали обычными разговорными словами у разработчиков но, на сколько мне известно, во многих вузах преподаватели говорят «шаблон», а не «паттерн».
По крайней мере когда я учился то преподаватели еще импользовали слово «шаблон».
Собственно начинающие разработчики скорее всего будут знать «шаблоны», а не «паттерны».

Да и людям, которые слабо знакомы с английским и только начинают познавать азы проектирования, слово «шаблон» будет более знакомо нежели «паттерн»(по крайней мере так было у многих людей с которыми мне доводилось общаться)

P.S. не подумайте что я с Вами спорю — просто хотелось изложить свою точку зрения и наблюдения.
Chef — на Ruby: https://github.com/chef/chef

Поэтому я и написал:
Помимо того, что он тоже не «на питоне» были еще какие-то аргументы?

Насчет Puppet хотябы был аргумент:
входной порог для старта работы с продуктом был достаточно высоким из-за сложной логики описания сценариев развертывания окружения.

а про Chef ничего не сказано.
А почему Вы не рассматривали «Chef»?
Помимо того, что он тоже не «на питоне» были еще какие-то аргументы?

Мы сейчас задумываемся о внедрении системы управления окружением, но больше смотрим в сторону Chef.
Chef кажется довольно продвинутым и гибким решением.
Я про то, что при реализации репозитория нет разницы, как именно внутри него всё работает.

Извините, я Вас неправильно понял. В этом я с Вами абсолютно согласен и собственно сам об этом и говорил=)
Какой-нибудь Row Data Gateway не лучше будет?

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


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

Моя основная идея — максимально использовать уже имеющуяся функциональность дабы не изобретать велосипеды.
К примеру в YII2 для ActiveRecord имеются такие поведения как ActiveRecord Role и ActiveRecord Variation, которые можно использовать для более гибкого построения модели предметной области.

К примеру: мы можем на уровне базы иметь таблицы «user» и «user_profile» для хранения основной (ник, почта и т.п.) информации о пользователе и его профиль (полное имя, день рождения и т.п.).
Сущность User в предметной области включает данные из обеих таблиц и для сущности не имеет значения как эти данные хранятся и что они разделены на несколько таблиц для обеспечения более оптимальной работы системы, построения отчетов и т.п.
С помощью «ActiveRecord Role» мы можкм отразить обе таблицы на одну сущность User средствами ActiveRecord и получить свою сущность предметной области абстрагированную от источника данных.
Даже без логики AR довольно удобен.


Вы абсолютно правы, но там где в одном случае все удобно, в другом это удобство может быть надгробием.
Я это говорю из собственного опыта — уже не один проект встречал, где все из «AR довольно удобен.» перерастало в «все пропало Михалыч».
В основном это происходило из-за увеличения сложности предметной области, а из-за подходов заложенных при первоначальном использовании AR уже довольно сложно было что-то менять.

Как говорится: «раз на раз не приходится». Проекты разные и то, что хорошо для большинства может быть убийцей.

P.S. Надеюсь я правильно понял о чем Вы, а то не до конца понятно к какому именно комментарию Ваш ответ.
1

Information

Rating
Does not participate
Location
Краматорск, Донецкая обл., Украина
Date of birth
Registered
Activity