Pull to refresh
41
0
Dmitriy T. @zibada

User

Send message
(смотрит) ну давайте мы внезапно еще что-нибудь узнаем про вашу задачу.

Про окружение посмеялся. Да-да, а перенастраивать все остальное как бы не надо. Само заработает.

* * *

У меня для вас есть рассказ — в далеком 1995м году я был такой же молодой и горячий. И тоже рисовал наколеночную отсылку почты, ровно в таком же ентерпрайзненьком стиле. Все было замечательно, пока не поставили этого кадавра клиентам. И тут! Тут началось.

Однажды, в пятницу вечером, то ли гроза выбила сетевушку, то ли уборщица зацепила шваброй провод — но оно таки случилось. И робот по отсылке почты тут же стал слать алерты — ну как же, отвалилось, примите меры. Отсылать было некуда, и все это ровно по вашему рецепту складывалось в БД.

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

И вот в понедельник с утра — пришел дежурный инженегр. Увидев, что все встало, он подцепил сетевой шнурок. Однако это не помогло. Обнаружив что на диске закончилось место, он удалил что-то ненужное.

Это не конец истории — дальше было вот что. Могучий досылатель, радостно заметив что почтовый сервер появился, тут же «дослал». SMTP там стоял какой-то древний демон на новеле, и от такого подарка он тут же сдох. Ну правильно — теперь на почтовом сервере место закончилось.

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

Что же было дальше? А вот что, досылатель снова обнаружил что почтовый сервер работает, и снова дослал новую порцию (да, я был креативным, и не пытался все письма залить сразу. Я разбил на порции. Предусмотрительный был, ага. А то бы сдох кадавр, и проблему решили бы быстрее).

Бам!

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

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

А через месяц вечером к большому боссу клиента пришел старинный приятель. И потребовал чаю. И секретарша, не найдя розетки поближе, выдернула раутер и включила чайник. О ее умственных способностях она узнала только утром. Чайник выдернули, вернули ценный аппарат на место… но кадавр-то не обесточен!

БАМ!!!

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

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

К слову, 10 лет спустя я был свидетелем демонтажа этого спарка. Единственный раз в жизни я видел слой пыли в системнике, который слежался до такой степени, что из него сразу можно было делать валенки. Первая мысль электронщика была «а зачем в корпус кусок пальто положили?»

Вы говорите — поцфикс не решает? ;-)
Какие капчи… Уже около месяца как API публично доступно:
$client = new SoapClient("http://voh.russianpost.ru:8080/niips-operationhistory-web/OperationHistory?wsdl");
$data=$client->GetOperationHistory(Array('Barcode'=>$rpo,'MessageType'=>0));
Таких сервисов миллион, причем даже тематических, к примеру —
flickholdr.com/
placehold.it/
dummyimage.com/
placekitten.com/
Ну и самые любимые — placezombies.com/ и placeboobs.com/ :)
«многопользовательская» — это какая? massive-multiplayer или просто multiplayer? Если второе, то как выше уже говорили, совсем не понятно зачем клиенту доверять так много. Да и в первом случае это имеет смысл только для оптимизаций(освободить сервер от «лишних» расчетов). Чаще всего под клиентом понимают просто какое-то примерное или приближенное отображение игрового состояния, т.е. абсолютно вся логика на сервере, а от клиента получаем только его действия/команды. И если уж все-таки посылать:
Клиент шлет свои координаты на сервер с какой-то периодичностью (Во время движения чаще)
Зачем так? Просто каждый кадр шлем с дельта-компрессией, соответсвенно если ничего не поменялось, нечего и отсылать будет.
Ну и TCP совсем не подходит для таких вещей, жаль что flash не поддерживает UDP сокеты. Хотя вон там у ребят получилось вроде неплохо :)
Если кому-то интересно, тут много информации по традиционному сетевому коду(не mmo):
* Source Multiplayer Networking
* Unreal Networking Architecture
* Quake3 Networking Model

Жду продолжения ;)
На самом деле это та же диллема, что от чего наследовать — прямоугольник от квадрата или квадрат от многоугольника. Она не разрешима, потому что:
1. Если следовать одной точки зрения, то непонятно, наследовать квадрат от прямоугольника или ромба
2. Если следовать другой точки зрения, то непонятно, наследовать параллелограмм от прямоугольника и от ромба.



На самом деле такие вещи появляются от непонимания сути OOP. Это массовое заблуждение, что ООП как-то связанно с объектами во внешнем мире и чем дальше — тем больше оно насаживается.

Я унаследовал эллипс от прямоугольника! Потому что Circle имеет centerPoint и radius, а эллипс и прямоугольник — точки «from» и «to». У них между собой более схожее поведение.
UFO landed and left these words here
UFO landed and left these words here
Язык программирования — для программиста. Необходимость в языке программирования и программировании в целом — это, повторю, борьба со сложностью. Чем более высоко абстрактен язык, тем эта борьба становится легче — путём человек-приближенных, высоко-абстрактных понятий ты описываешь ту или иную систему.

Так вот, если, например, в биологии, для моего удобства, чтобы мне легче было «побороть некую хаотичность» я могу классифицировать объекты — т.е. группировать их по особому набору признаков; разделять их; видеть закономерности (опять же — набор свойств) у одного объекта, и видеть, что они отличаются у другого объекта, то почему бы мне этого не сделать в программировании?

Опять же, ООП всего лишь теоретическая парадигма разработанная идеологами задолго до реализаторов движков и языков. Её удобно применять для решения конкретных задач — и именно где требуется (либо просто удобно) классификация структур по определенному признаку. В других задачах ООП может и не требоваться.

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

В некоторых языках (Java, C++, др.) класс напрямую связан с понятием типа. Но в общем же случае, для того, чтобы иметь возможность классифицировать, нужен лишь классификационный тег (classification tag). Иногда называют тегом типизации (type tag) или, опять совсем просто — типом. Это некоторое свойство (или набор свойств в общем случае), которое позволяет однозначно определить объект твоей классификации от объекта с таким же набором свойств.

Как я отметил выше, первая главная операция в ООП — это возможность порождать (construct) объекты. Если мы примем, что объект — это просто «набор свойств и поведений», то синтаксически мы можем прям так эти свойства со значениями и описывать:

var point = {x: 1, y: 2};


Если нам нужно три «точки», то:

var a = {x: 1, y: 2};
var b = {x: 3, y: 4};
var c = {x: 5, y: 6};


Но очевидно, что повторное использование кода (code reuse) методом «copy-paste» — это примитивная методика программирования (что если нам понадобится 100, 1000 точек?). Поэтому нам нужен некий удобный сахар для генерации объектов со схожей структурой. И самый простой способ сделать это — это использовать обычную функцию (да-да, точно так же, как мы всегда делаем, когда код повторяется больше двух раз — так называемое «правило двух» — «если код повторяется больше двух раз, вынеси (инкапсулируй) его в функцию».

function makePoint(x, y) {
  return {
    x: x,
    y: y
  };
}

var a = makePoint(1, 2);
var b = makePoint(3, 4);
var c = makePoint(5, 6);


Преимущество очевидно — если в дальнейшем детали реализации точки изменятся, нам нужно будет поменять код только в одном месте. Кстати, именно это и называется инкапсуляцией, и именно в этом её основная суть — отделение уровня реализации точки и уровня использования точки. Если уровень использования не будет трогать внутренности реализации, то реализация может меняться хоть каждый день — при том же внешнем интерфейсе для использования.

Так вот, основная цель конструктора, как показано выше — это всего лишь удобный код реюз — генерация однотипных объектов.

Но. Чтобы классифицировать твои объекты, недостаточно их просто генерировать. Нужен классифицирующий тег. Т.е. у собаки тоже 4 конечности, но она отличается от человека.

Например, это может быть имя функции, которая создала объект. А лучше — ссылка на неё. Можно поместить этот тег прямо в самом объекте, но очевидно, что можно выделить вспомогательный спец. объект и задействовать делегацию — так, тег будет храниться в единственном экземпляре и будет доступен всем нашим объектам. Назвать его можно прямо и в лоб — constructor (вспомогательный объект при этом назовем prototype):

makePoint.prototype = {
  constrcutor: makePoint
};


И модифицированный способ создания:

function makePoint(x, y) {
  return {
    __proto__: makePoint.prototype,
    x: x,
    y: y
  };
}


Повторим, посредством делегации мы добьемся следующего эффекта:

a.constructor // a.constructor -> not found, a.__proto__.constructor -> found == makePoint.


Разработав всё это (нашу фабрику «makePoint» по генерации объектов-точек), мы придём к выводу, что некоторые вещи можно оптимизировать, убрать сложность (мы ж со сложностью боремся!):

1. уберём (да, для сахара) этот префикс «make», заменим его ключевым словом «new»;

2. сделаем return опциональным (правда, на кой ляд он нам в общем случае? — пусть система сама знает, что надо вернуть объект);

3. будем создавать вспомогательный объект автоматически за кадром и устанавливать __proto__ тоже «по-тихому» (ты хочешь повторять это ручками каждый раз? — я нет);

4. введём какое-нибудь специальное слово (например, this), чтобы ссылаться на созданный объект и не писать каждый раз эти скобочки { и }. Хотя, тут двояко, иной раз со скобками удобней.

5. что-нибудь ещё придумаем…

В итоге, мы получим систему конструкторов в JS:

function Point() { // no "make"
  this.x = x;
  this.y = y;
}

var a = new Point(1, 2);
var b = new Point(3, 4);
var c = new Point(5, 6);

a.constructor // Point


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

Технические хаки (типа «я щас подменю свойство constructor» и т.д.) — меня, как программиста, вааапще не касаются. Удобно мне так классифицировать объекты — я классифицирую. Не буду я ничего ломать, подменять constructor, использовать поломанный [[Class]] в каком-нибудь движке и т.д.; я буду просто программировать в классифицирующем стиле. Если мне надо.

Если не надо. Пожалуйста — полный арсенал утилит для бесклассового (хаотичного) реюза. Здесь уже никакой классифицирующий тег, естественно, не нужен. Здесь уже наоборот, другой объект, если он крякает, как мой, тоже (по идее!) пройти «тест на утку».

В итоге, в JS (как и в любом другом языке с делегацией) можно программировать как с классами, так и без них. Но в классовой системе нельзя программировать в бесклассовом режиме.

Information

Rating
Does not participate
Registered
Activity