Как стать автором
Обновить

Разработка снизу-вверх и базы данных.

Время на прочтение 5 мин
Количество просмотров 3.6K
    Пол Грэм в своих эссе часто касается темы разработки снизу-вверх. Этот метод упоминается у него, когда он пишет о разработке програмного обеспечения, о способе ведения бизнеса, о преимуществах open source и блогах. Ниже я опишу почему при этой модели разработки взаимодействие с базой данных встает поперек глотки, и предложу решение уместное в некоторых случаях.

    Нельзя сказать, что метод снизу-вверх лучше какого-либо другого, просто в большестве случаев он более жизнеспособен. Действительно, человек открывая, например, магазин или создавая DE начнет с малого и постепенно будет развивать его; но если он уже развил свой магазинчик в сеть магазинов, сравнимую с Auchan, или написал KDE, то в следующий раз он уже не будет начинать с малого, а проведет долгое время в планах и затем реализует большой проект сразу. В первый раз человек получает обратную связь во время разработки, во второй раз тоже, правда он уже разрабатывает уже не магазин, а последовательность магазинов, и отклик полчает от предыдущего разработанного проекта.

    В крупных компаниях разработка часто ведется сверху вниз. К сожалению, простые исполнители из-за этой методики начинают не любить свою работу, так как у них пропадает элемент творчества. Пол в своем эссе What business can learn from open source предложил интересную модель разработки, когда компания занимающаяся производством ПО, инвестирует деньги в команды программистов, которые уже занимаются разработкой в той области, которая интересна компании. Таким образом пропадает иерахия босс-подчиненный и разработчики работают с большем энтузиазмом, а компания занимается вопросами маркетинга, дистрибуции и не содержит собственный штат программистов. Из примеров, которые на слуху у читателей хабра — язык F#, над котором долгое время работал Don Syme и который microsoft решила пустить в mainstream в следующем релизе студии.

    В своих эссе Пол делает основной упор на преобладание практики над планированием, скоростью написания и легкостью изменения. К сожалению, многие средства для разработчиков создавались без оглядки на эти принципы и были нацелены на те компании, которые придерживаются сложившегося отношения босс-подчиненный. Часто, при работе в XP стиле взаимодействие с базой данных встает как кость в горле: сложности при тестировании; гетрогенность кода — думать приходиться то на ЯВУ, но на декларативном SQL, имея ввиду ньюансы отображения одного на другое; огромное количество ненужного кода и ненужных абстракций, которые отвечает за взаимодействие с базой, а решения, которые призваны это безобразие исправить, по сути являются кодогенерацией со всеми вытекающими из этого проблемами.

    Первыми этот бардак осознали люди, пишушие на динамических языках — и попытались исправить эту проблему. Так появились couchdb, strokedb и simpledb. Это решение подходит для небольших проектов, но думаю компании уровня яндекс не будут держать свои базы на субд, которые не прошли тестирование временем.

    Представим, что на дворе 95 год, вы проснулись и решили создать яндекс, то есть создать движок для web-поиска. Очевидно, что самое интересное в задаче это анализ информации, а не способ её хранения, поэтому вы сразу набросились на эту задачу. Частично её решили и хотите сделать первый прототип, что бы найти инвестора. Ясно, что без хранения данных здесь уже не обойтись, но с другой стороны вы понимаете, что какую-либо структуру базы вы не выбрали, то к моменту запуска она сто раз измениться, поэтому от перспективы писать сто раз workaround для работы с базой вас тошнит.

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

    Если мы хотим написать свой простой движок базы данных, то это легко сделать используя язык, который поддерживает кортежи, списки и list comprehension, а так как реализация движка базы данных это не основная задача, которая перед нами стоит, то желательно, что бы этот язык был высокого уровня, обладал привычным синтаксисом и поддерживал популярные парадигмы. Думаю вы уже догадались, что я пишу о nemerle. Ниже я привиду примитивный пример реализации движка БД.

    Допустим схема базы следующая:
DROP TABLE IF EXISTS Author;
CREATE TABLE Author (
  ID INT AUTO_INCREMENT NOT NULL,
    Firstname VARCHAR(500) NOT NULL,
    Lastname VARCHAR(500) NOT NULL,
    PRIMARY KEY(ID)
);

DROP TABLE IF EXISTS Journal;
CREATE TABLE Journal (
  ID INT AUTO_INCREMENT NOT NULL,
    Title VARCHAR(500) NOT NULL,
    PRIMARY KEY(ID)
);

DROP TABLE IF EXISTS Article;
CREATE TABLE Article (
  ID INT AUTO_INCREMENT NOT NULL,
    Title VARCHAR(500) NOT NULL,
    JournalID INT NOT NULL,
    AuthorID INT NOT NULL,
    CONSTRAINT `journal_id` FOREIGN KEY (JournalID) REFERENCES Journal(ID) ON DELETE CASCADE,
    CONSTRAINT `author_id` FOREIGN KEY (AuthorID) REFERENCES Author(ID) ON DELETE CASCADE,
    PRIMARY KEY(ID)
);


* This source code was highlighted with Source Code Highlighter.


    Реализовать эту структуру и пару запросов к ней можно следующем образом.

public interface IDB
{
 AddAuthor(firstName : string, lastName : string) : int;
 GetAuthor(firstName : string) : list[int*string*string];
}

public class MyDB : IDB
{
 public this() { Author = []; Journal = []; Article = []; ID = 0; }
 public Author : list[int*string*string] { get; set; }  // (ID, Firstname, Lastname)
 public Journal : list[int*string] { get; set; }     // (ID, Title)
 public Article : list[int*string*int*int] { get; set; } // (ID, Title, JournalID, AuthorID)
 public ID : int { get; set;};
 
 public AddAuthor(firstName : string, lastName : string) : int
 {
  ID++;
  Author = (ID,firstName,lastName)::Author;
  ID
 }
 
 public GetAuthor(firstName : string) : list[int*string*string]
 {
  $[(id,first,last)|(id,first,last) in Author, first==firstName]
 }
}


* This source code was highlighted with Source Code Highlighter.


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

cc-by-nc-sa
Теги:
Хабы:
+5
Комментарии 6
Комментарии Комментарии 6

Публикации

Истории

Ближайшие события

PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн
Weekend Offer в AliExpress
Дата 20 – 21 апреля
Время 10:00 – 20:00
Место
Онлайн