标签: software-design

我应该跨多个微服务共享模型吗?

我正处于一个大项目的分析阶段,该项目将使用微服务架构创建。我非常有信心(至少在未来 3 年)整个代码库将用 TypeScript 编写,并且大多数模型将在这些服务之间使用。

我计划使用微服务来构建它,因为每个模块都将是一个单独的 API,它将拥有其 REST 端点来处理与其职责相关的任务。例如,身份服务将处理注册、身份验证、令牌更新等......

我计划将每个服务创建为独立的 NestJS 项目。及其存储库、包、依赖项等......

但我有一个疑问:

这些服务是否应该在内部声明每个模型?即使它可能是在另一个服务中声明的相同模型?这可能会导致项目之间出现大量代码重复,对吗?

如果他们不这样做,并且他们应该定义模型的只读子集,其中仅包含他们需要的属性,那么当“源”模型发生更改时,哪一个是在不同服务之间保留子集更改的最佳方法?假设服务A定义了模型X,服务B使用X的一个子集(称为X1 ),服务B使用X的另一个子集(称为X2 )。每当某个属性可能发生更改(被删除、更改类型、名称或其他)时,当这些项目可能有 10 个、20 个或更多时,哪种方法是在每个项目之间保持此更改同步的最佳方法?

我很困惑,因为据我所知,微服务应该是独立的,并且拥有它运行所需的一切,所以遵循这个逻辑让我认为服务应该重新声明原始模型的相同副本或子集,住在另一个服务中。

但从代码重复的角度来看,这似乎是一种自杀,因为第一年我将是唯一一个从事这些项目的人。

我知道微服务架构更适合开发团队,但是团队会来,所以在不久的将来可能会有 3/4 的人在做它,每个人都会有几个服务需要维护和维护发展。

在此先感谢任何愿意帮助我解决这个疑问的人!

architecture software-design reusability

20
推荐指数
2
解决办法
1万
查看次数

跟踪实用程序类

我最近对我在项目代码库中出现的问题越来越感到沮丧.

我正在开发一个拥有> 1M行代码的大型java项目.接口和类结构设计得非常好,编写代码的工程师非常精通.问题在于,为了使代码更清晰,人们在需要重用某些功能时编写实用程序类,随着时间的推移,随着项目的增长,越来越多的实用程序方法出现.但是,当下一位工程师遇到对相同功能的需求时,他无法知道有人已在代码中的某处实现了实用程序类(或方法),并在另一个类中实现了该功能的另一个副本.结果是大量代码重复和太多具有重叠功能的实用程序类.

我们作为一个团队可以实施任何工具或任何设计原则,以防止实用程序类的重复和低可见性吗?

示例:工程师A有3个位置需要将XML转换为String,因此他编写了一个名为XMLUtil的实用程序类,并toString(Document)在其中放置一个静态方法.工程师B有几个地方将文档序列化为各种格式,包括String,因此他编写了一个名为SerializationUtil的实用程序类,并且有一个名为static的方法serialize(Document),它返回一个String.

请注意,这不仅仅是代码复制,因为上述示例的2个实现很可能是不同的(例如,一个使用变换器API而另一个使用Xerces2-J),因此这可以被视为"最佳实践" "问题也是......

更新:我想我更好地描述了我们开发的当前环境.我们使用Hudson进行CI,使用Clover进行代码覆盖,使用Checkstyle进行静态代码分析.我们使用敏捷开发,包括日常会谈和(可能不充分)代码审查.我们在.util中定义了所有的实用程序类,由于它的大小现在有13个子包,在根(.util)类下有大约60个类.我们还使用第三方库,例如大多数apache commons jar和一些组成Guava的罐子.

我很肯定,如果我们让某人完成重构整个软件包的任务,我们可以减少一半的公用事业,我想知道是否有任何工具可以降低成本,并且有任何方法可以可以尽可能地延迟重复出现的问题.

java usability software-design code-duplication

19
推荐指数
2
解决办法
2395
查看次数

如何理解VIPER清洁架构?

我最近发现了VIPER干净的架构,我开始寻找在Android平台上应用这种架构的示例教程.然而,我唯一发现的是样本项目让我感到困惑,这就是为什么我想按照一个简单的例子来理解VIPER的基本原则.我想知道是否有人可以在上面分享一些很好的教程.

architecture android software-design viper-architecture

18
推荐指数
2
解决办法
8567
查看次数

如何在C++中选择堆分配与堆栈分配?

将其与其他语言区分开来的C++特性之一是能够将复杂对象分配为成员变量或局部变量,而不是总是必须分配它们new.但这导致了在任何给定情况下可以选择哪个问题.

是否有一些很好的标准来选择如何分配变量?我什么时候应该将成员变量声明为直接变量而不是作为引用或指针?什么时候应该分配一个变量new而不是使用在堆栈上分配的局部变量?

c++ scope memory-management software-design c++11

17
推荐指数
1
解决办法
4056
查看次数

请问java RMI的意义吗?

为什么人们使用RMI,或者什么时候应该使用RMI?我在oracle的网站上阅读了关于RMI的那些教程.但它没有提供足够的实际例子.

根据我的理解,软件的模块应尽可能"无关和分离".RMI似乎是一个与我高度耦合的例子.为什么这不是一个糟糕的编码实践?我认为客户端应该只发出指令,而对象的所有实际操作都是由服务器完成的.

(我目前正在攻读计算机科学学士学位并且缺乏经验,所以如果我理解这些概念错误,请纠正我.)

提前致谢!

java computer-science rmi anti-patterns software-design

17
推荐指数
3
解决办法
7030
查看次数

构造函数,模板和非类型参数

我有一个类必须依赖于int模板参数的某些原因.
出于同样的原因,该参数不能成为类的参数列表的一部分,而是它的构造函数的参数列表的一部分(当然,模板化).

这里出现了问题.
也许我错过了一些东西,但是我看不到向构造函数提供这样一个参数的简单方法,因为它不能推断也不能明确指定.

到目前为止,我发现了以下替代方案:

  • 将上述参数放入类的参数列表中

  • 创建工厂方法或工厂函数,可以作为示例调用 factory<42>(params)

  • 为构造函数提供traits结构

我试图为最后提到的解决方案创建一个(不那么)最小的工作示例,以便更好地解释问题.
示例中的类不是自身的模板类,因为关键点是构造函数,无论如何真正的模板类是模板类.

#include<iostream>
#include<array>

template<int N>
struct traits {
    static constexpr int size = N;
};

class C final {
    struct B {
        virtual ~B() = default;
        virtual void foo() = 0;
    };

    template<int N>
    struct D: public B{
        void foo() {
            using namespace std;
            cout << N << endl;
        }

        std::array<int, N> arr;
    };

 public:
     template<typename T>
     explicit C(T) {
         b = new D<T::size>{};
     }

     ~C() …
Run Code Online (Sandbox Code Playgroud)

c++ templates constructor software-design traits

17
推荐指数
1
解决办法
1005
查看次数

python:抽象基类'__init __():初始化还是验证?

class ABC是一个"抽象基类".class X是它的子类.

有些工作需要在任何子类中完成ABC,这很容易忘记或做错.我想ABC.__init__()通过以下两种方式来帮助解决这些错误:

(1)开始这项工作,或(2)验证它

这会影响super().__init__()是在开始时还是在结束时调用X.__init__().

以下是用于说明目的的简化示例:

假设每个子类ABC必须具有一个属性registry,并且它必须是一个列表.ABC.__init__()可以(1)初始化registry或(2)检查它是否正确创建.以下是每种方法的示例代码.

方法1:在ABC中初始化

class ABC:
    def __init__(self):
        self.registry = []

class X:
    def __init__(self):
        super().__init__()
        # populate self.registry here
        ...
Run Code Online (Sandbox Code Playgroud)

方法2:在ABC中验证

class ABC:
    class InitializationFailure(Exception):
        pass
    def __init__(self):
        try:
            if not isinstance(self.registry, list):
                raise ABC.InitializationError()
        except AttributeError:
            raise ABC.InitializationError()

class X:
    def __init__(self):
        self.registry = []
        # populate self.registry here
        ...
        super().__init__()
Run Code Online (Sandbox Code Playgroud)

哪个更好的设计?

python oop abstract-class software-design

16
推荐指数
1
解决办法
1万
查看次数

如果成员也是按层次结构构建的,那么如何构建类结构?

我正在构建一个PHP Web应用程序,它应该为用户提供在他和另一个人/组织之间订购(ConnectDirect或File Transfer Gateway)连接的"安装"/设置的可能性.

(连接实现的技术细节并不重要 - 在应用程序中,它只是作为产品的连接,可以订购和管理.)

其模型层的类层次结构应代表以下实际基础结构:

  • 连接,可以订购.
  • 连接可以是IBM Connect:Direct连接或IBM File Transfer Gateway连接.
  • CD连接是从A(直接)到B(目标).
  • FTGW连接包括物理上的两个连接的:A(源)到FTGW服务器,并从服务器FTGW到B(目标) -但在逻辑上(用于排序的用户)它也是一个连接.
  • (还有一个FTGW连接的情况,它使用Connect:Direct作为protokoll.)
  • 每个端点都是源或目标.

所以我看到以下逻辑元素:逻辑连接,物理连接,角色(目标),连接类型,顺序,端点,端点类型(CD和FTGW).

我目前的结构如下:

连接和端点伪UML类图

但它有一些问题:

  1. 2种层次结构的树,其中每个元件的一个的含有特定的元素的子集的其他(各CD连接的由CD端点;每个FTGW连接包括两个FTGW端点,或更正确地:每个FTGW逻辑连接包括两个物理FTGW连接 - 每个连接由一个FTGW端点和FTGW服务器组成,作为第二个端点).

    另一种可能是替代的关系betweet EndpointPsysicalConnection通过两个关系:EndpointCD-PsysicalConnectionCDEndpointFTGW-PsysicalConnectionFTGW.

取代了关系

:更一致; 消除了从一对任何端点构建每个连接(类型)的伪造可能性的逻辑不精确(或甚至可能是错误 …

php architecture inheritance software-design class-structure

16
推荐指数
1
解决办法
476
查看次数

洋葱建筑与六角形相比

它们之间有什么区别(洋葱|六角形),从我的理解它们是相同的,它们关注的是应用程序核心的领域,应该是技术/框架不可知的.

它们之间有什么区别?

另外我认为使用一个优于另一个甚至是针对N层架构没有真正的优势,如果做得不好只是跟随其中任何一个都没有任何区别

使用一个优于另一个以及为什么要使用它有什么好处?什么时候用?

谢谢

architecture software-design hexagonal-architecture onion-architecture

16
推荐指数
2
解决办法
5401
查看次数

完整新手的设计原则?

我已经编程了大约一年了,而且我编写的所有东西都有用 - 从我的观点来看,它写的非常糟糕.我想知道是否有关于软件设计的任何(免费)好书可以为初级程序员提供一点指导?如果我对软件设计的思考过程有所了解,我认为我没有那么多问题.

python software-design

15
推荐指数
3
解决办法
2299
查看次数