Найти - Пользователи
Полная версия: Обратное наследование
Начало » Python для экспертов » Обратное наследование
1 2 3 4 5
o7412369815963
zheromo
Есть еще один вариант, основанный на генерации классов по их описанию
в zope вроде тоже описание в отдельных файликах лежит (xml)

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

во внешний файлик можно вынести порядок подключения плагинов, из cms их подключать/отключать сортировать…
zheromo
o7412369815963
работает быстрее
генерироваться определение класса будет только при инициализации системы
o7412369815963
ошибки искать
ошибки теоретически в момент генерации и должны выявлятся (или у нас не динамическая типизация? :))
o7412369815963
zheromo
o7412369815963
работает быстрее
генерироваться определение класса будет только при инициализации системы
o7412369815963
ошибки искать
ошибки теоретически в момент генерации и должны выявлятся (или у нас не динамическая типизация? :))
1) в лучшем случае так, но зависит от реализации зависит.
2) типизация ни причем, ошибки могут быть хоть где, в простом коде их проще искать.
zheromo
o7412369815963
типизация ни причем
на мой взгляд даже как :)
Андрей Светлов
Излагаю свое мнение.

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

С trac более или менее ясно. Как по мне - достаточно простая и красивая система.
Теперь о прочих вариантах, которые я здесь увидел. Варианты zheromo мне показались довольно запутанными. В силу этого не уверен, что они будут удобны и достаточно универсальны. Быть может, я ошибаюсь.

Вариант o7412369815963 проще и радикальней. Только он все равно избыточный.
Если при создании системы вопросы взаимодействия плагинов (не только с системой, но и между собой - что будет если два плагина подерутся за одно место?) - забота плагинописателей, то самое простое и гибкое (дальше некуда) решение - импортировать плагин а там пусть он сам крутится как может.
Дополнительных усилий прилагать не нужно.
Если в следующей версии плагины поломаются - это чужая головная боль. Равно как авторам плагинов самим придется заботится о совместной работе с коллегами. Это - цена неимоверной гибкости. Конечно, потом уже в самих плагинах появятся адаптеры, интерфейсы и точки входа - просто потому, что поддерживать такую невероятно гибкую систему в рабочем состоянии стоит очень больших усилий и постоянной головной боли.

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

zheromo, если изучали trac не убоявшись интерфейсов - посмотрите еще и на Zope Component Arcitecture.
o7412369815963
Андрей Светлов
Если при создании системы вопросы взаимодействия плагинов (не только с системой, но и между собой - что будет если два плагина подерутся за одно место?) - забота плагинописателей, то самое простое и гибкое (дальше некуда) решение - импортировать плагин а там пусть он сам крутится как может.
Я за “импортировать плагин а там пусть он сам крутится как может”, а на счет конфликтов пусть думает “архитектор” какие ему плагины применять.
Вот когда cms будет популярна и под неё начнут штамповать плагины, тогда можно заняться улучшением и наворотами плагинов.

На счет конфликтов - можно сделать список, в который все плагины будут перечислять что они подменили, добавили. В итоге можно будет посмотреть какие модули где пересекаются.
Андрей Светлов
Список не поможет, mockey patching - трудно формализуемая операция. Думаю, достаточно будет просто списка загруженных плагинов чтобы экспериментально определять, где что и как.

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

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

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

Все хорошо, но возникло два вопроса.

1. Обычно я стараюсь много чего выносить в конфиги. Приведу пример, так роутинг я обычно описываю в отдельном файле (yaml) как-то так:
    index:
view: views.index.index
url:
- /
- /page/<int:page>
renderer: actions/index/index.html
acl: VIEW
Описания меню вынесены также в конфиги:
        index:
order: 100
title: blog_menu_all
counter: views.new.count_topics_new
submenu:
index:
order: 100
title: blog_menu_all_good
new:
order: 200
title: blog_menu_all_new
counter: views.new.count_topics_new
hide_if_zero: true
Плагину чтобы дописать что-то в меню достаточно указать в своем конфиге:
        index:
submenu:
plugin:
order: 150
title: blog_menu_plugin
title автоматом попадает в gettext, а index, new, plugin являются endpoint-ами и соответственно автоматически подсвечиваются.

Напомню что речь идет про Flask.
В стиле же Trac получается примерно такой код:

class IRouteProvider(Interface):

def connect():
"""Mount endpoint & routes of view.
Format: (enpoint, route1, route2, ...)
"""

def handle(context, request):
"""Process the request."""

class INavigationContributor(Interface):
"""Extension point interface for components that contribute items to the
navigation.
"""

def get_active_navigation_item(request):
"""This method is only called for the `IRouteProvider` processing the
request.

It should return the name of the navigation item that should be
highlighted as active/current.
"""

def get_navigation_items(request):
"""Should return an iterable object over the list of navigation items to
add, each being a tuple in the form (category, endpoint, title, counter [optional],
hide_if_zero [optional], quotted [optional]).
"""

class IndexModule(Component):
'''Main page
'''

required = True
implements(INavigationContributor, IPermissionRequestor, IRouteProvider)

# INavigationContributor methods

def get_active_navigation_item(self, request):
return 'index'

def get_navigation_items(self, request):
return [( .... )]

# IPermissionRequestor methods

def get_permission_actions(self):
return ['VIEW']

# IRouteProvider methods

def connect(self):
return ('index', '/', '/page/<int:page>',)

def handle(self, context, request, page=1):
return 'actions/index/index.html', dict( ... )
Можно конечно пойти гибридным способом и что-то оставить в конфигурационных файлах, а что-то в самом коде компонента.
На мой взгляд в некоторых случаях конфиг лучше, в плане что не надо менять код, чтобы изменить например вид урлов, порядок сортировки навигации и т.д.

Хотелось бы услышать мнение по этому вопросу.

2. И второе. Так как на мой взгляд архитектура Фласка несколько отличается от компонентной, то приходится переписывать некоторые части его функционала которыми я раньше пользовался а теперь не могу.

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

class ITemplateProvider(Interface):
def get_template_loader():
'''Возвращает загрузчик шаблонов'''
def get_translations():
'''Возвращает класс GNUTranslations либо путь к каталогу'''

class BroserView(Component):
"""Web site chrome assembly manager."""

required = True
implements(IRouteProvider, ITemplateProvider)

navigation_contributors = ExtensionPoint(INavigationContributor)
template_providers = ExtensionPoint(ITemplateProvider)

+ много буков по имплементации всего этого добра
Лично у меня получается что чтобы интегрировать функционал фреймворка в код требуется больше усилий, чем написать свою реализацию.

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

Хотелось бы также понять, отчего возникает дискомфорт, либо просто от неумения пользоваться интерфейсами, либо по причинам, которые я попытался изложить выше.
Андрей Светлов
Эээ. А flask и есть именно - микро. И именно роутинг -это та задача, которую он обязан решать.
Все прочее - полезные, но не обязательные надстройки.
Мне нужно посмотреть на ваш код внимательней прежде чем говорить что-то еще.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB