有没有一种编程范例可以促进使依赖关系对其他程序员来说非常明显?


26

我在一个数据仓库中工作,该数据仓库通过许多流和层为多个系统提供源,并且具有迷宫般的依赖关系,将各种工件链接在一起。几乎每天我都会遇到这样的情况:我运行某些东西,它不起作用,运行大量代码,但是几个小时后,我意识到我已经设法将现在所知的一小部分概念化为流程图需要一天的稍后时间,所以我问一个人,他们告诉我必须先运行另一个流,并且如果我在这里检查(表明其他编码依赖项的巨大堆栈中某些看似任意的部分),则我将看到了这个。真令人沮丧。

如果我能够向团队建议,如果我们做更多的事情来使对象之间的依赖关系更加可见和明显,而不是将它们深深地嵌入到递归代码级甚至数据中,那可能是个好主意。之所以必须存在,是因为它被另一个流填充了,也许是通过引用一个众所周知的,经过测试的软件范例进行的,那么我也许可以使我的工作变得简单,而其他所有人都可以简化很多。

向我的团队解释这种好处是很困难的。他们倾向于按照现状接受事物,而不是“想大”,因为他们看到了能够以新方式概念化整个系统的好处–他们并没有真正看到是否可以为大型系统建模高效,那么就不太可能遇到内存效率低下,流停止唯一约束和重复键,废话数据的情况,因为这样可以更轻松地进行设计以符合原始视觉,并且以后不会遇到所有这些问题我们现在正在经历,我知道这与以往的工作不同寻常,但他们似乎认为这是不可避免的。

那么,有谁知道一个强调依赖关系并促进系统通用概念模型以确保长期遵守理想的软件范例?目前,我们几乎陷入了混乱,每个冲刺的解决方案似乎都是“只是在这里,这里和这里添加此东西”,而我是唯一一个担心事情真的开始崩溃的人。


2
您能澄清一下这些是什么“连接各种工件的迷宫式依赖项”吗?他们是否在构建依赖关系,可以通过Maven之类的构建工具来解决?它们是输入依赖项吗?这些伪像之一依赖于某些不明显或不清楚的输入吗?它们是数据库表之间的关键依赖性吗?
FrustratedWithFormsDesigner

系统是PLSQL,Unix bash,OWB等,因此存在各种依赖性。有时,某个模块需要在特定位置,特定位置,特定时间,特定位置以某种格式要求数据,但是从代码中并不能很明显地看出数据,只能通过两种方式来辨别:通过遍历大量的代码,可能要花几天的时间,才能发现某些数据在系统的一部分中有一个定界的半冒号,您甚至不知道该数据被引用了,因为它被埋在10层递归调用代码中,或者通过询问某人,所有时间,每次。它不会促进独立。
Christs_Chin

4
从字面上看所有这些
Miles Rout

3
小切线:由于Haskell是惰性的,因此在编写代码时实际上没有指定操作顺序。您仅指定依赖项。函数C取决于函数A和B的结果。因此,必须在C之前运行A和B,但是如果首先运行A或首先运行B,则它可以同样好地工作。我只是觉得那很有趣。
GlenPeterson

1
有一本叫做《设计模式》的书(这本书很烂,但是除了单例之外,它的大部分内容都是不错的)。它具有管理依赖关系的几节。
ctrl-alt-delor

Answers:


19

可发现性

它的缺席困扰着许多组织。弗雷德再次构建的那个工具在哪里?确保在Git存储库中。哪里?

我想到的软件模式是Model-View-ViewModel。对于初学者来说,这种模式是一个完全的谜。我以“五个漂浮在桌子上的小部件通过某种神秘的力量互相交谈”的方式向妻子解释了这一点。了解了模式,您就了解了软件。

许多软件系统无法记录其体系结构,因为他们认为该体系结构是不言自明的,或者是自然地从代码中出现的。不是,不是。除非您使用定义明确的体系结构,否则新人们会迷路。如果没有记录(或众所周知),那么新人将会迷路。一旦退伍了几个月,退伍军人也会迷路。

团队有责任提出合理的组织架构并将其记录在案。 这包括类似

  • 文件夹组织
  • 项目参考
  • 类文档(它是什么,它做什么,它为什么存在,如何使用)
  • 项目,模块,装配体,以​​及任何文档。

使事情井井有条,容易发现是团队的责任,这样团队就不会不断地重新发明轮子。

顺便说一句,“代码应该是自我记录的”这一概念只是部分正确的。 的确,您的代码应该足够清晰,因此您不必在每行代码中都加上注释,但是诸如类,项目,程序集,接口之类的工件之间的关系并不明显,而且仍然需要记录在案。


3
当然可以,但是过于依赖设计模式的人就是问题的一部分。他们是编写代码而没有任何文档的人,前提是其他所有人只要看一下代码就能了解他们到底做了什么。同样,软件设计模式不是体系结构(大部分情况下)。
罗伯特·哈维

1
弗雷德再次构建的那个工具在哪里?确保在Git存储库中。哪里?没错!MVC模式对于前端开发而言太具体了(我认为),并且只有当团队中的每个人都知道这种模式时,这种模式才有用,所以这只是将问题从不明显的依赖关系转移到了明显的依赖关系(如果每个人都知道如何找到)他们。但是问题是事实并非如此。因此,我希望有某种方法能够促进一种非常明显的方式来解释依赖关系,而无需其他学习过的概念框架来使用。
Christs_Chin

7
它称为“文档”。除此之外,您还需要一个每个人都支持的明智的依赖框架。不幸的是,没有一个样板模板可以直接放入项目中。该软件的组织结构是您的团队在明智的架构的帮助下创建的。
罗伯特·哈维

5
@RobertHarvey:最近听说:“我们编写不需要文档的代码”。错误。您正在编写没有文档的代码。
gnasher729

3
这里有一些好东西。注意:编写不需要注释的代码和编写支持文档之间是有区别的。
罗比·迪

10

解决此类问题的最佳方法是逐步解决。不要沮丧,并提出广泛而全面的架构更改。这些将永远不会被批准,并且代码将永远不会得到改进。假设您甚至可以确定要进行的正确的,广泛的架构更改,这是不可能的。

什么可能的是,你能确定一个较小的变化,将帮助您与您刚刚解决特定的问题。也许反相一些依赖,增加了一些文件,创建一个接口,编写缺少的依赖,警告脚本等,所以提出的是更小的变化来代替。更好的是,根据您的公司文化,他们可能会容忍甚至期望您在最初的任务中进行类似的改进。

当您进行这些较小的更改时,这是您日常工作的一部分,并且以您的榜样为例,鼓励其他人也这样做,随着时间的推移,它们确实会累加起来。比抱怨不允许进行的单个较大更改要有效得多。


2
我同意渐进式变更的想法。问题是,如果没有一些组织原则,您可能会造成更多混乱。考虑仅将单个项目,类或其他工件(其他模块依赖于此)移到更合理的位置的效果。
罗伯特·哈维

1
好东西。几个勤奋的灵魂经常使我的艰苦工作变得艰辛,他们乐于在这里和那里添加工具/小工具以从混乱中创造秩序。虽然我不喜欢大量文件,但写得很好的备忘单或要点/功能的要点列表可以极大地帮助您。
罗比·迪

+1提出可能会获得批准的小更改。我体会到了这一点,它帮助我成为了更有影响力的人,然后我的建议就产生了更大的影响力。
RawBean '17

2

建筑。

没有单一的,特定的,通用的原则或实践可以解决适用于所有软件各个方面的可发现性和可维护性问题。但是,使项目明智的东西的广义术语是建筑。

您的架构是围绕潜在(或历史)混乱的每个点进行决策的整体,包括指定如何制定和记录架构决策。关于发展过程中,文件夹结构,代码质量,设计图案应有尽有,等等都可能去的所有东西进入你的架构,但他们没有一个人一个架构。

理想情况下,这些规则是由单一思想统一而成的

一个小的团队当然可以协作创建架构。但是,有不同的意见,这将很快导致一个非常精神分裂症的架构,不用于保持理智。确保您的体系结构以及其中的许多TLA和模式都以一种唯一的心态为团队的成功服务的最简单方法就是让一个人为它们负责。

现在,这并不一定需要“建筑师”来推崇而且,尽管有些团队可能希望有经验的人来做出这些决定,但主要要点是有人需要拥有该体系结构,尤其是随着团队的成长。有人要时刻注意团队的动向,适度的架构讨论,记录决策,并监控决策并继续努力以遵守架构及其精神。

我不是一个人做出所有决定的忠实拥护者。但是,确定负责主持架构讨论并记录决策的“架构师”或“技术产品所有者”可抵御更大的弊端:责任的扩散导致无法辨别架构。


您将责任的扩散确定为对可辨别的体系结构不负责任是绝对正确的。现在仅在最近才决定解决此问题。我一直认为,一个好的解决方案是通过另一个软件系统创建一个完整的分布式系统,该软件系统充当各种工具,您可以在其中决定系统中要包含的内容,但可以根据架构师的编程方式来决定在何处。您将对多种不同的系统和技术有一个看法,并将通过一些系统架构图对其进行导航...
Christs_Chin

我认为您在此答案中的观点是打击/预防OP所谈论的事情的唯一最大方法。它甚至适用于继承OP一样的混乱情况。
GWR

1

欢迎来到软件工程(两种意义上);)这是一个很好的问题,但是实际上,没有简单的答案,我相信您已经知道了。这确实是随着时间的推移逐步发展为更好的做法,训练人们提高技能的一种情况(按定义,该行业中大多数人的能力中等)...

作为一门学科的软件工程首先要构建它,然后按时设计它的思想,一方面是出于权宜之计,另一方面是出于必要。这只是野兽的天性。当然,随着时间的推移,黑客会逐渐建立在黑客的基础上,因为上述编码人员会迅速部署功能解决方案,这些解决方案通常会以引入技术债务为代价来解决短期需求。

您需要使用的范例本质上是培养更好的人才,培训您有才能的人才,并强调在计划和架构上花时间的重要性。在单片系统上工作时,很难说是“敏捷”的。即使进行很小的更改,也可能需要进行大量计划。完善高级文档编制流程还将帮助关键人员更快地掌握代码。

您可能会关注的想法是(随着时间的推移逐渐地)隔离和重构系统的关键部分,使它们更加模块化和分离,可读性,可维护性。关键是要根据现有的业务需求来工作,以便在减少技术债务的同时实现可见的业务价值。因此,解决方案一方面是改进实践和技能,另一方面是试图朝着长期的架构思维发展,正如我已经告诉您的那样。

请注意,我已经从软件开发方法论的角度而不是从编码技术的角度回答了这个问题,因为实际上这是一个比编码甚至架构样式的细节还重要的问题。这实际上是您如何计划更改的问题。


6
我听到您在说什么,但您的回答最终还是令人不满意,并且坦率地说有点侮辱。这不仅是雇用更好的人,而是更大的问题。即使是在我工作的小商店里,我们也为此感到挣扎,我认为这不仅仅是一个人的问题。我认为它有一些特定的技术难题。
罗伯特·哈维

1
我同意有技术方面的内容,但是与强调采用更强大的计划变更方法相比,我认为这些方面相对较小。我不认为这与设计模式有关,而与文化转向更多的计划和分析,更早的计划和分析以及更好的计划和分析无关。
布拉德·托马斯

好吧,我将发布自己的答案作为比较。我不认为这有什么做软件模式。
罗伯特·哈维

布拉德,谢谢您的回答。非常感谢您的答复,因为我知道我并不孤单。在我的团队中似乎就是这样。我也同意罗伯特·哈维(Robert Harvey)的观点,因为这个问题很普遍,我不想放弃这样一种信念:无论是在新型软件还是在新的工作方式中,都有解决方案。
Christs_Chin

2
正是我的经验:您必须让团队成员了解他们在做什么。我看到人们将MVVM和MVC混合在一起,其他人以Windows窗体(或更确切地说是VB6)正常的方式使用WPF控件,人们使用C#进行编程,但对对象定向没有基本的了解...教他们。再次教他们。沮丧。再次教他们,...经常想放弃。并再次教他们...
Bernhard Hiller

1

我喜欢@RobertHarvey的约定概念,并认为它们会有所帮助。我也喜欢@KarlBielefeldt的想法,“随手编写文档”,并且知道这很重要,因为这是使文档保持最新状态的唯一方法。但是我认为最重要的想法是,记录如何找到代码的所有部分,构建和部署它们很重要!

我最近通过电子邮件发送了一个重要的开源项目,该项目具有一些XML配置,生成的代码完全没有文档记录。我问维护者,“ XML代码生成过程记录在哪里?测试数据库设置记录在哪里?” 他说:“不是。” 这基本上是一个单一贡献者的项目,现在我知道为什么了。

看,如果您是那个人并且正在阅读本文,我真的很感谢您在做什么。我几乎崇拜您的劳动成果!但是,如果您花了一个小时来记录您真正具有创造力的东西是如何组合在一起的,那么我可能会花几天时间编写可以为您提供帮助的新功能。当面对“缺少文档不是问题”的砖墙时,我什至不会尝试。

在企业中,缺少文档会浪费大量时间和精力。诸如此类的项目通常会被提供给顾问,而后者的成本更高,只是为了使他们能够弄清诸如“所有部件在哪里以及它们如何组合在一起”之类的基本知识。

结论

所需要的不是技术或方法论,而是文化的转变。共同的信念是,记录事物的构建方式和原因很重要。它应该是代码审查的一部分,这是与生产相关的生产要求。当每个人都相信并采取行动时,事情就会改变。否则,就像我在开源项目中失败一样。


2
我怀疑文化问题的部分原因在于敏捷的信念,即“如果它不是用户故事的一部分(即,它不直接影响利益相关者的价值),那么它就不重要了。” g。 这里的相关对话:在敏捷中,如何计划和分配项目开始时的基本基础架构任务?
罗伯特·哈维

@RobertHarvey是的。我们团队中的每个人都很聪明,相处也非常容易。Scrum主管和项目经理的意图和驱动力很好,实践是我工作过的最敏捷的方法。但是缺少文档,可能是出于您建议的原因。另外,当创建文档时,在沟通有效性的另一层随机性引入了该人识别相关概念并进行解释的能力,更不用说他们对必须执行此类任务的态度了。通常这只是“问问”
-Christs_Chin

@GlenPeterson是的,我同意这会有所帮助。但是,不仅应该指定它应该被构建,而且应该指定如何以及什么可以作为文档。例如,这里有一个最近的示例,有人在其中包含了我们的系统将识别的新数字列表。而已。没有提及这些数字如何进入系统,在何处,为什么,由谁,多久或有用的信息,只有它们起作用。我毫不怀疑我们的系统将识别出哪些数字是相关的。但是我经常想知道,它们进入哪里,去哪里以及在途中发生了什么。这仍然是一个谜。
Christs_Chin

1
@Christs_Chin大量的交流是基于上下文的。没有这种背景,大多数交流几乎毫无意义。我感到你很痛苦。但是我认为很难(英语)写出来,这样其他人才能理解你。有时,系统的早期规格会包含您需要了解它的上下文,即使它们已经过时,该上下文通常也会有所帮助。
GlenPeterson

1

要回答所提出的问题(而不是针对您的特定情况提供建议):

称为纯函数编程的编程范例要求影响函数输出的所有内容都必须在输入参数中指定。在代码库中没有隐藏的依赖项,全局变量或其他不可思议的作用。没有“您必须先执行此操作”的时间耦合。


0

每个数据仓库都是不同的,但是您可以做很多事情来使事情变得容易。

首先,数据库中的每一行都有一个DATE_ADDEDDATA_UPDATED列,因此我们可以看到何时将其添加到数据库中以及何时对其进行了更改。我们也有一个SOURCE_CODE列,因此我们可以跟踪每一位数据进入系统的位置。

接下来,我们在所有数据仓库中使用了通用工具,例如排序,表匹配,切片器和切块器等。

定制的代码保持在绝对最低限度,即使如此,它也必须确认各种编码和报告样式。

我假设您已经熟悉ETL套件。这些天,您免费获得了许多功能,而十年前我在玩游戏时还没有。

您可能还需要查看数据集市,以提供更友好,更卫生的数据仓库版本。当然,这不是灵丹妙药,但可以帮助解决某些问题,而不必重建/纠正数据仓库。


感谢您的答复。是的,我们使用了所有这些字段,但它们仅真正帮助识别单行,而不帮助流,层和系统之间的依赖关系。您对ETL套件的看法是正确的-我们正在从一个不再受支持的工具升级到一个著名的ETL工具,但最终又回到了PLSQL。可以很好地进行编码,但是对于可维护性以及从代码级别理解整个系统而言,这绝对是可怕的。
Christs_Chin

1
理想的情况是,您可以通过登台表或平面文件来端对端地跟踪数据,但是如果没有这些数据,则剩下的是遍历代码。
罗比·迪

0

我不知道这与您的案例有多大的相关性,有一些策略可以使依赖关系更加可见,并且可以对代码进行常规维护-

  • 避免使用全局变量,而应使用参数。这也适用于跨语言通话。
  • 尽可能避免更改/更改变量的值。如有可能,请在需要更改值时创建一个新变量并使用。
  • 使代码模块化。如果无法描述什么(而不是如何)部分实际上是在做一个简单的句子,把它分解成满足条件的模块。
  • 正确命名您的代码部分。当您实际上可以用简单的术语描述一部分代码在做什么时,这些术语便成为该部分的名称。因此,代码通过模块/类/功能/过程/方法等的名称变为自记录文件。
  • 测试您的代码。测试代码中的实体是否证明其名称合理,如前所述。
  • 在代码中记录事件。至少保持两个级别的日志。第一个始终处于启用状态(即使在生产中也是如此),并且仅记录关键事件。并使用另一个来记录基本上所有内容,但是可以打开或关闭。
  • 查找并使用合适的工具来浏览,维护和开发您的代码库。即使在某些情况下,Visual Studio Code的一个简单的“搜索所有内容”选项也使我的生活变得轻松很多。
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.