管理一个应用程序的多个专用版本的最佳实践

发布于 2024-07-08 05:35:13 字数 1169 浏览 6 评论 0原文

我有一个有很多面孔的网络应用程序,到目前为止我已经通过创建主题来实现这一点。 主题是一组与公共后端一起使用的 html、css 和图像。

事情是这样安排的:

code/
themes/theme1
themes/theme2

Web 应用程序的每个实例都有一个配置文件,用于说明应使用哪个主题。 示例:

theme="theme1"

现在新的业务规则要求我对某些主题进行更改,而这些主题无法通过简单更改 html/css/images 来实现,并且需要更改后端。 在某些情况下,这些更改需要应用于一组主题。

我想知道如何最好地将其放置在磁盘上,以及如何在代码中处理它。 我确信其他人一定也遇到过这个问题。

一个想法是:

code/common
code/theme1
code/theme2
themes/theme1
themes/theme2

然后让我的通用代码设置 include_path,以便首先搜索 code/theme1,然后搜索 code/common

然后,如果我想专门为 theme2 指定 LogoutPage 类,我只需将页面从 code/common 复制到 下的同一路径即可code>code/theme2 它将选择专用版本。

这种想法的一个问题是会有多个具有相同名称的类。 尽管理论上它们永远不会包含在同一个执行中,但我无法扩展原始基类。

那么如果我要为基类取一个唯一的名称呢? 例如Theme1LogoutPage 扩展了LogoutPage。 我可以预见的一个问题是,当某些常见代码(例如调度程序)引用 LogoutPage 时。 我可以向调度程序添加条件,但我想知道是否有更透明的方法来处理这个问题?

我能想到的另一个选择是为每个主题维护单独的分支,但我认为这可能需要大量工作。

最后要考虑的一件事是,功能可能源自一个主题,然后需要合并到公共代码库中。

任何意见都非常感谢。 如果说有什么不同的话,那就是 LAMP 环境。

I have a web application that has many faces and so far I've implemented this through creating themes. A theme is a set of html, css and images to be used with the common back end.

Things are laid out like so:

code/
themes/theme1
themes/theme2

And each instance of the web application has a configuration file that states which theme should be used. Example:

theme="theme1"

Now new business rules are asking me to make changes to certain themes that can't be achieved through simply change the html/css/images and require changing the backend. In some cases these changes need to be applied to a group of themes.

I'm wondering how to best lay this out on disk, and also how to handle it in code. I'm sure someone else must have come up against this.

One idea is to have:

code/common
code/theme1
code/theme2
themes/theme1
themes/theme2

Then have my common code set the include_path such that code/theme1 is searched first, then code/common.

Then if I want to specialize say the LogoutPage class for theme2, I can simply copy the page from code/common to the same path under code/theme2 and it will pick up the specialized version.

One problem with this idea is that there'll be multiple classes with the same name. Although in theory they would never be included in the same execution, I wouldn't be able to extend the original base class.

So what if I was to make a unique name for the base class? e.g. Theme1LogoutPage extends LogoutPage. One problem I can foresee with that is when some common code (say the Dispatcher) references LogoutPage. I can add conditions to the dispatcher, but I wonder if there's a more transparent way to handle this?

Another option I can think of is to maintain separate branches for each theme, but I think this could be a lot of work.

One final thing to consider is that features might originate in one theme and then require merging into the common codebase.

Any input greatly appreciated. If it makes any difference, it's a LAMP environment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

毁我热情 2024-07-15 05:35:13

我没有具体的建议。 但是,我强烈建议不要走捷径...使用您会觉得舒适的解决方案来添加第三个主题或明年更改某些内容。
重复是可维护性的敌人。

I don't have a specific recommendation. However, I strongly suggest to NOT take shortcut... Use the solution that will you will find comfortable to add a third theme or to change something next year.
Duplication is the enemy of maintainability.

挽梦忆笙歌 2024-07-15 05:35:13

我会研究使用策略模式作为在网站的不同版本中实现不同功能的方法。 有一个工厂接受您的配置并根据它提供适当的代码策略。 每个策略都可以实现一些通用接口,以便从调用类的角度来看它们是可以互换的。 这将隔离您对工厂类、配置类以及您需要实现的任何新策略类实施新策略的更改。 您可以对需要在不同版本之间有所不同的任何用户控件执行相同(或类似)的操作。

我将用伪代码(可能看起来可疑地像 C#)来说明

public interface ILogoutStrategy
{
   void Logout();
}

public abstract class AbstractLogoutStrategy : ILogoutStrategy
{
   public virtual void Logout()
   {
      // kill the sesssion
   }
}

public class SingleSiteLogoutStrategy : AbstractLogoutStrategy
{
   public void Logout()
   {
      base.Logout();
      // redirect somewhere
   }
}

public class CentralAuthenticationSystemLogoutStrategy : AbstractLogoutStrategy
{
   public void Logout()
   {
      base.Logout();
      // send a logout request to the CAS
      // redirect somewhere
   }
}

public static class StrategyFactory
{
   public ILogoutStrategy GetLogoutStrategy(Configuration config)
   {
      switch (config.Mode)
      {
         case Mode.CAS:
            return new CentralAuthenticationSystemLogoutStrategy();
            break;
         default:
         case Mode.SingleSite:
           return new SingleSiteLogoutStrategy();
           break;

      }
   }
}

示例用法:

ILogoutStrategy logoutStrategy = StrategyFactory.GetLogoutStrategy( config );
logoutStrategy.Logout();

I'd investigate using the Strategy pattern as a means to implement different functionality in different versions of the site. Have a Factory that takes in your configuration and supplies the appropriate code strategy based on it. Each strategy can implement some common interface so that they are interchangeable from the calling class' point of view. This will isolate your changes to implement new strategies to the Factory class, Configuration class, and any new strategy classes that you need to implement to make the change. You could do the same (or similar) with any user controls that need to differ between the different versions.

I'll illustrate with pseudocode (that may look suspiciously like C#)

public interface ILogoutStrategy
{
   void Logout();
}

public abstract class AbstractLogoutStrategy : ILogoutStrategy
{
   public virtual void Logout()
   {
      // kill the sesssion
   }
}

public class SingleSiteLogoutStrategy : AbstractLogoutStrategy
{
   public void Logout()
   {
      base.Logout();
      // redirect somewhere
   }
}

public class CentralAuthenticationSystemLogoutStrategy : AbstractLogoutStrategy
{
   public void Logout()
   {
      base.Logout();
      // send a logout request to the CAS
      // redirect somewhere
   }
}

public static class StrategyFactory
{
   public ILogoutStrategy GetLogoutStrategy(Configuration config)
   {
      switch (config.Mode)
      {
         case Mode.CAS:
            return new CentralAuthenticationSystemLogoutStrategy();
            break;
         default:
         case Mode.SingleSite:
           return new SingleSiteLogoutStrategy();
           break;

      }
   }
}

Example usage:

ILogoutStrategy logoutStrategy = StrategyFactory.GetLogoutStrategy( config );
logoutStrategy.Logout();
〃安静 2024-07-15 05:35:13

您使用母版页吗? 如果您需要不同的布局和 UI 内容,您可以为每个实例使用一组不同的母版页。 如果您需要自定义行为,那么您可能需要研究依赖注入。 Spring.NET等

Are you using Master Pages? If you need different layout and UI stuff you could just have a different set of master pages for each of your instances. If you need custom behavior then you might want to look into Dependency Injection. Spring.NET, etc.

鯉魚旗 2024-07-15 05:35:13

你需要的是模板。

这样您就可以将代码与演示文稿分开。

我强烈推荐 smarty 模板。 还有 PEAR template_it。

http://www.smarty.net/

这也使您的代码更易于维护。 目的是让你的php中没有html,并且让你的html中没有php。

那么您需要做的就是更改每个主题使用的 html 模板。 或模板文件夹。

What you need are templates.

Thence you can separate your code from your presentation.

I highly recommend smarty templates. Also PEAR template_it.

http://www.smarty.net/

This also make your code far more maintainable. The aim is to have no html in your php, and to have no php in your html.

then all you will need to do is change the html template that is being used for each theme. or folder of templates.

生生不灭 2024-07-15 05:35:13

你可以有:
/common/code

并且:
/sitename/code

/common/code 中的所有文件都是抽象类。
对于 /common/code 中的每个文件,只需在 /sitename/code 中创建一个相应的非抽象类文件,该文件继承自 /common/code 中的抽象类。

这样你只需要在 /sitename/code 中实现 CHANGES
其他一切都是仅存在于 /common/code 中的核心功能。

这里要做的重要事情是确保仅将 public 方法添加到抽象类中。 这样,这些方法可用于所有站点,并且可以以相同的方式处理/使用所有站点的类。

You could have:
/common/code

And:
/sitename/code

All files in /common/code are abstract classes.
For every file in /common/code, just create a corresponding non-abstract class file in /sitename/code that INHERITS from the abstract class in /common/code.

This way you only need to implement CHANGES in the /sitename/code
Everything else is core functionality that exists only in /common/code

The important thing to do here is ensure that you only add public methods to the abstract classes. This way the methods are available to all sites, and classes from all sites can be treated/worked with identically.

韶华倾负 2024-07-15 05:35:13

我会这样做:

[主题名称]/[子文件夹]
默认/通用
默认/通用/html
默认/通用/CSS
红色/代码
红色/普通
红色/常见/html
红色/通用/css
红色/代码
绿色/普通
green/common/html

因此,如果代码或任何其他组件不存在,它将回退到默认值。

但事实上我会在 svn 中对网站进行分支,因此如果通用代码发生变化,我可以合并它,等等。请参阅 Subversion:http://subversion.tigris.org/

I would do:

[theme name]/[subfolder]
default/common
default/common/html
default/common/css
red/code
red/common
red/common/html
red/common/css
red/code
green/common
green/common/html

So if the code or any other component doesn't exist it will fall back to default.

But in fact I would branch the website in svn, so common code if it evolves I can merge it, etc.. see Subversion at: http://subversion.tigris.org/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文