我应该按业务领域还是技术领域来组织文件夹?


19

例如,如果我使用某种类似于MVC的体系结构,则应使用哪种文件夹结构:

domain1/
    controller
    model
    view
domain2/
    controller
    model
    view

要么:

controllers/
    domain1
    domain2
models/
    domain1
    domain2
views/
    domain1
    domain2

我故意省略了文件扩展名,以使该问题与语言无关。

就个人而言,我更喜欢按业务领域(直觉)分开,但我看到大多数/许多框架都按技术领域分开。为什么我要选择谁呢?


2
框架针对开发人员,而不针对业务用户。预计开发人员会对技术性方法更满意,并且框架将其考虑在内-这可能是您观察到的原因
咬到了2012年

Answers:


15

我认为这取决于特定的项目。

例如,如果不同的业务领域彼此完全独立,那么我将按业务领域进行组织。

但是,如果业务域之间存在共享代码,或者说业务域是同一代码库的不同变体,那么按技术领域进行组织似乎更加合乎逻辑。而且,如果您使用任何一种面向对象的语言,那么您可能可以在特定于业务的文件中将通用控制器,模型等子类化,以使其更薄。

两者之间还有一个(黄金)过渡-将共享代码剥离到自己的域中,并在其他域中使用它。这为您提供了直觉式的布局,但允许在业务域之间共享代码。

Domain1              # This domain changes bits of standard MVC code
  controllers
  models
  views
Domain2              # this domain only modifies views, all else is standard
  views
Shared               # Here is the better part of code base
  controllers
  models
  views

PS。我认为大多数框架都是按技术领域组织的,因为它们倾向于期望只有在共享代码的情况下,您才将不同的业务领域混合到单个项目中,否则将创建单独的项目。

编辑:

例如,假设有一个处理公司仓库的Web应用程序。以通用形式,这可能适用于许多公司,但每个公司可能都有一些未满足的特定条件,并禁止他们购买。例如,其中一个已将平板电脑部署到叉车上,需要为它们提供特殊的视图,而另一个则需要将项目分为三个级别,而不是默认的两个级别。

您当然可以为这些公司中的每一个分叉该项目。但是,如果框架/语言允许,则可以使用子类化或插件等来定制通用项目的各个部分,以满足每个客户的需求,并在Business Domain布局中进行组织。

例如,如果通用项目仅将Item本身导出为JSON,则Domain1可以将控制器子类化,并使其也导出最近的交付问题。

并且,如果以后您发现Domain1具有对Domain2也有效的组件,则可以将其通用版本提取到Shared。

如您所说,许多框架是按技术领域组织的,而这正是我目前使用的框架,因为我选择的固件使这变得容易。但是,用一点(或很多)手肘油脂,我想我也可以重写include路径来支持Business Domain布局。


我认为这个主意很棒,但是我无法想象一个实际的例子。您能给一个简单却有启发性的例子吗?
Florian Margaine 2012年

@FlorianMargaine-我给你一个真实的例子。房地产网站。在我的上一份工作中,我们向许多客户出售了一些房地产网站。我们为所有50多个客户提供了一个集中式数据库。每个后端管理员使用一组共享的模块。每个面向客户的方面都使用了独特的图像和导航。每个搜索页面和向下钻取页面都使用共享模块,除非客户需要一次性功能。对于那些一次性的事情,我们将代码分开,并给他们自己的模块。(缺点:升级必须以通用方式完成,并在一次性模块中重复)
Michael Riley-AKA Gunny,2012年

8

我想问一个启发性的问题:“我更有可能定期添加更多的领域或更多的技术部门吗?” 然后,无论答案是什么,都将其放在顶层。

在大多数情况下,您的技术架构将比您的领域更快地固化。这意味着您应该首先按领域进行组织,然后再按体系结构组件进行组织。原因是,当某个域中的某些内容发生更改时,您可能必须在该域中添加或更改多个技术组件,但是希望它已本地化并且不会过多地传播到其他域中。

如果您更改了GUI框架,则意味着您的更改将散布在整个应用程序中,但是同样,您很少更改GUI框架,但是您总是在更改域逻辑。

如果它们可能同时发生变化,请将它们放在一起。


最佳建议,但我看不出如何预测我将添加最多的域名。
Florian Margaine 2012年

最后一句话很钉钉。
哈坎·德里亚

@FlorianMargaine-我认为域名的“种类”并不重要。如果添加的域多于添加新的技术“事物”,则应首先按域对所有内容进行分组。
Scott Whitlock,2012年

3

还有另一种选择,那就是移动插件中的各个部分。例如,CakePHP就是这样做的。它将允许您生成可重复使用的完整MVC部件,您可以根据所需的逻辑对其进行排序。

您的主应用程序将只使用它们并链接到它们。

基本上,您的问题也与凝聚力和耦合有关。您希望各个部分尽可能独立地工作。这样,您就可以获得可测试和可重用的代码。

考虑到这一点:如果按域划分,将如何重用应用程序的某些部分?例如,在网上商店:/ orders / view / 1发出了请求,因此您需要显示订单号。1.转到/ orders / controllers / order_controller如果按产品和订单分隔域,则您将已经需要其他“域”的一部分。

在那里,您可以开始连接事物,但是在大多数业务中,事物可能过于紧密。如果您采用技术方法。例如,您可能有一个插件来处理订单。您从中央应用程序中将产品对象放入其中。这样,您可以轻松测试插件,只需创建一个带有名称和价格的Product对象并将其发送。

该插件将完全满足其需要。这将取决于它的输入,而不取决于其他“部分/域/区域”。


好主意。从本质上讲,这是我的回答。我将共享代码放在顶部,并且基本上插入了域特定信息。您将域放在顶部,然后插入共享代码。我认为,对于去耦和可测试性而言,两者都是同样好的方法。
Laas 2012年

2

Microsoft ASP.Net MVC 3具有“区域”的概念。当您在MVC项目中引入“区域”时,它们会像下面那样分解:

area1/
   models
   views
   controllers
area2/
   models
   views
   controllers

我发现这很自然。区域是项目的“大块”,在一个独立的单元中工作很有意义。

我们使用名称空间来匹配FWIW。


2
感谢您的贡献,但这如何回答我的问题?(比较这两种解决方案)
Florian Margaine 2012年

@FlorianMargaine:我正在说明微软是如何做到的,并假设(可能有缺陷)他们在选择更明智的方法上投入了大量的工程努力。希望它能提供一些输入。
gahooa 2012年

好的,但这就是我在问题中展示的面向业务的方式……
Florian Margaine 2012年

1

从我在一个包含30万行代码的网上商店的个人经验中,我总是会去按业务领域进行组织。这样,当您在一个功能区域上工作时,不仅可以快速概览所有相关类,而且在Java中,您还可以利用包的可见性。

对感兴趣的人的一些详细信息:5年前启动该项目时,开发人员创建了以下包结构:

com
  example
    web
      struts
        action
        form
      shared
      functionality1
      functionality2

每个商店功能(例如购物车,产品搜索等)都包含多个动作,每个动作都有其自己的表单类(由MVC框架强制要求的结构)。我们最终得到的是动作包中的200多个类,每个类都与其关联的表单类完全分开。更糟糕的是,动作没有实现太多的逻辑,而是调用驻留在另一个程序包中的特定于功能的服务。

我建议并说服了团队,我们应该改用按业务领域组织软件包。道理很简单:如果您真的想查看所有动作的列表,则只需打开任何体面的IDE的类型层次结构视图即可。但是,IDE无法做的是推断类所属的业务域。此外,该方法允许您仅公开几个功能所需的类,而其余的则保留在包可见性上。


0

我同意许多框架按技术领域分开,因此我经常在使用新框架时以这种方式开始。但是,我始终坚持使用业务域作为文件夹组织的主要级别。

就个人而言,我认为将Foo Controller和Foo Repository或其他内容保持在一起要比在Controller的文件夹和Repository的文件夹之间来回切换要容易得多,因为在Foo周围添加功能时,我经常需要同时进行这两个工作。在较大的项目中,这尤其重要,因为技术文件夹之间的距离可能很大,并且在开发时会浪费大量时间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.