代码混淆 增加垃圾代码_代码如何成为垃圾场(以及如何解决!)

代码混淆 增加垃圾代码

Earlier in my career, I faced a sort of career crisis.

在我职业生涯的早期,我面临着某种职业危机。

I was part of a team creating a large analytics platform in the automotive industry. This application had the typical "enterprise-y" layered architecture you would expect ("Business Layer", "Data Access Layer", "Core", etc.).

我是一个在汽车行业创建大型分析平台的团队的成员。 该应用程序具有您所期望的典型的“企业级”分层体系结构(“业务层”,“数据访问层”,“核心”等)。

You would expect to find business logic - the really important business logic - embedded somewhere inside of the code from these layers. But, usually, the really important business rules were coded into stored procedures.

您将期望从这些层中找到嵌入在代码内部某处的业务逻辑-真正重要的业务逻辑。 但是,通常,真正重要的业务规则已编码到存储过程中。

Stored procedures, if you don't know, is like a function you create inside of a database that uses an SQL-like syntax to process data, store it, etc.

如果您不知道, 存储过程就像您在数据库内部创建的函数一样,该函数使用类似于SQL的语法来处理数据,进行存储等。

I wondered what the purpose of the layers was. They didn't have any code except for passing data to stored procedures or showing data returned by one.

我想知道这些层的目的是什么。 除了将数据传递到存储过程或显示一个返回的数据外,他们没有任何代码。

I started to learn more about object-oriented programming, industry best-practices, SOLID, other programming paradigms, application architecture, etc.

我开始学习有关面向对象编程,行业最佳实践,SOLID,其他编程范例,应用程序体系结构等的更多信息。

From this career crisis, I discovered that these problems have already been solved! It just takes research, time and practice to learn and grow skilled in them.

从这次职业危机中,我发现这些问题已经解决了! 仅需研究,时间和实践,即可学习并发展其中的技能。

面向对象? (Object-Oriented?)

One thing I discovered is that all the projects I've been on that were doing "Object-Oriented" programming were not doing true OOP. Just because you use classes doesn't mean you are doing OOP. Especially if you are using stored procedures to encode all your business rules.

我发现的一件事是,我所从事的所有正在做“面向对象”编程的项目都没有完成真正的OOP。 仅仅因为您使用类并不意味着您在做OOP。 特别是当您使用存储过程对所有业务规则进行编码时。

简而言之:大辩论 (A Short Aside: The Great Debate)

It needs to be brought up: is object-oriented programming or functional programming better?

需要提出来:面向对象编程还是函数编程更好?

For starters, most people don't understand what OOP was intended to be in the first place. Similar to how Agile today is usually misunderstood (e.g. just because you are having daily stand-ups, using story points, kanban, etc. it doesn't mean you are doing Agile).

对于初学者来说,大多数人根本不了解OOP的初衷。 类似于今天通常被误解为敏捷的方式(例如,仅仅因为您每天站起来,使用故事点,看板等,这并不意味着您在进行敏捷)。

Alan Kay is considered one of the fathers of OOP. In a certain email, he gave some frank explanations about what OOP was supposed to be.

艾伦·凯(Alan Kay)被认为是OOP的父亲之一。 在一封电子邮件中 ,他对OOP应该是什么做了一些坦率的解释。

"I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful)...
“我想到的对象就像是生物细胞和/或网络上的个人计算机,只能与消息进行通信(因此消息传递从一开始就出现了,花了一段时间才知道如何以一种编程语言足够有效地进行消息传递有用)...
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things...
对我而言,OOP意味着仅消息传递,本地保留和保护以及状态过程的隐藏以及所有事物的极端后期绑定...
But just to show how stubbornly an idea can hang on, all through the seventies and eighties, there were many people who tried to get by with 'Remote Procedure Call' instead of thinking about objects and messages."
但是,只是为了表明一个想法可以顽固地坚持到整个七十年代和八十年代,有很多人试图通过“远程过程调用”来解决这个问题,而不是考虑对象和消息。”

For those familiar with microservices, the actor model, and other advanced programming paradigms, your Spidey sense is tingling. These are actually more closely related to true OOP.

对于那些熟悉微服务,参与者模型和其他高级编程范例的人来说,您的Spidey感觉有点刺痛。 这些实际上与真正的OOP密切相关。

So, is FP better than true OOP?

那么,FP比真正的OOP好吗?

I don't think so. I think they both have their merits. Many languages today are embracing both paradigms and allowing developers to use the tools and methods that work best for the given problem!

我不这么认为。 我认为他们都有优点。 当今,许多语言都同时包含这两种范式,并允许开发人员使用最适合给定问题的工具和方法!

What you'll usually find are classes that expose all their properties or internal data members. An HTTP request or database query will fill-up all the properties, and then, perhaps, something else will work on that object's data.

通常会发现是公开其所有属性或内部数据成员的类。 HTTP请求或数据库查询将填满所有属性,然后,也许其他一些东西将对该对象的数据起作用。

Instead of what Alan Kay intended to be as little "bundles" that pass messages to each other (see aside above), most developers are using objects as mere "data holders". Glorified variables, as it were.

并非Alan Kay打算成为将消息彼此传递的“小束”(见上文),而是大多数开发人员将对象用作“数据持有者”。 光荣的变量,因为它是。

What you'll also find in many codebases are very generic classes like User, Customer or Order.

您还会在许多代码库中找到非常通用的类,例如UserCustomerOrder

Is that bad? Well, yes.

那不好吗? 好吧, 是的

Let me ask you a question:

让我问你一个问题:

Is User used in many different unrelated places in your application?

User是否在应用程序的许多不同无关位置使用过?

For example, is your User class used in the billing part of your code, the user profile parts, the shipping parts, etc.?

例如,您的User类是否在代码的计费部分,用户个人资料部分,运输部分等中使用?

Most systems are doing something like that.

大多数系统都在做类似的事情。

What will end up happening is that, because these classes are so generic, they become dumping grounds for code which we don't know where it belongs.

最终将发生的事情是,由于这些类是如此通用, 因此它们成为我们不知道其所属位置的代码的垃圾场。

Instead of taking the time to think about the business need for this new code we've written, often we feel that it's easier to put into our generic classes. It's all shareable, right? And we're all about code-reuse, right?

与其花时间去思考我们编写的新代码的业务需求,通常我们会觉得将其放入通用类更容易。 都是共享的,对不对? 我们都是关于代码重用的,对吗?

耦合 (Coupling)

So... what if I changed the User class to conform to some billing logic? What are the chances that I've also broken the shipping feature by changing this class? I don't know, but it's higher than 0%.

那么...如果我更改User类以使其符合某些计费逻辑该怎么办? 通过更改此类,我也有可能破坏运输功能吗? 我不知道,但高于0%。

This User class has coupled all your features together. This causes lots of problems.

User类将您的所有功能结合在一起。 这引起很多问题。

Ideally, we want our code to be orthogonal (that's just a fancy word that means changing code in one place won't affect other unrelated places).

理想情况下,我们希望代码是正交的(这只是一个花哨的词,这意味着在一个位置更改代码不会影响其他无关的位置)。

We want to be able to change the shipping feature, for example, and not have to test our entire application again. But, if we're sharing our User class everywhere then, to have confidence that we didn't break stuff, we need to re-test everything.

例如,我们希望能够更改运输功能,而不必再次测试我们的整个应用程序。 但是,如果我们到处都在共享User类,要确保我们不会破坏东西,就需要重新测试所有内容。

This leads to a fear of changing code. The fear of making our code better. It also leads to a lot of bugs.

这导致担心更改代码。 担心使我们的代码更好。 它还导致许多错误。

If you are building out the payment feature for your application - you shouldn't have to think about whether you are breaking the shipping feature at the same time! This causes a huge cognitive load that doesn't need to be there.

如果您要为应用程序构建付款功能,则不必考虑是否同时破坏了送货功能! 这会导致巨大的认知负担,而不必在那里。

另一个:警告标志 (Another Aside: Warning Sign)

Overall, I find that the idea of segmenting your business features/functions via different physical folders or even entirely different projects altogether is best. I've written about this before.

总体而言,我发现最好是通过不同的物理文件夹甚至完全不同的项目对业务特征/功能进行细分。 我以前已经写过这个

But, when it comes to our code at a deeper level, we can still tend to design our classes and objects in a way that's still too generic and leads to much coupling.

但是,当涉及到更深层次的代码时,我们仍然倾向于以过于通用的方式设计类和对象,并导致大量耦合。

Anytime I find classes that have simple names like User or Customer, a warning signal goes off. I'd much rather see classes that are created for a specific context.

每当我找到具有简单名称(例如UserCustomer ,就会发出警告信号。 我宁愿看到为特定上下文创建的类。

For example, if I saw a class named UserForAuthentication or PaymentsCustomer then I would be more confident that these classes aren't being thrown around and reused in too many contexts.

例如,如果我看到一个名为UserForAuthenticationPaymentsCustomer的类,那么我会更有信心这些类不会在太多上下文中被抛出或重用。

Here's a basic way that might help get started on analyzing your classes. Take your class name and answer these questions:

这是一种基本的方法,可能有助于开始分析您的课程。 以您的班级名称并回答以下问题:

Is there a subject? (user, client, order, etc.)

有主题吗? (用户,客户,订单等)

Is there a context for that subject? (shipping, orders, dashboard, etc.)

这个主题有背景吗? (运输,订单,仪表板等)

Is there even perhaps an action being performed on the subject? (as we'll see in more details soon)

甚至可能正在对该主题执行操作吗? (我们将在后面详细介绍)

If you cannot answer 2 of those questions then I'd say there's a good chance that your class might be doing too much by being too generic.

如果您不能回答其中两个问题,那么我想说您的课堂很有可能因为过于通用而做得太多。

这些事情之一与其他事物不同 (One Of These Things Is Not Like The Others)

There's a programming principle called the Single Responsibility Principle.

有一种编程原则称为“单一责任原则”。

When looking at classes or methods that are doing too much, using the SRP as a guiding light can help us to make code that is easier to maintain, less coupled and therefore leads to fewer bugs.

当查看做得太多的类或方法时,使用SRP作为指导可以帮助我们制作更易于维护,耦合更少并因此导致更少错误的代码。

Let's look at a generic User class that might be similar to code you've seen before:

让我们看一个通用的User类,它可能与您之前看到的代码相似:

class User {
    public firstName: string;
    public lastName: string;
    public id: number;
    public jwtToken: string;
    public homeAddress: string;
    public creditCardNo: string;

    public getFullName(): string {
        return this.firstName + " " + this.lastName;
    }

    public decodeJwtToken(): string {
        return decode(this.jwtToken);
    }
}

Look familiar?

看起来熟悉?

Given the name of the class, we should start to be suspicious that it's too generic of a class.

给定类的名称,我们应该开始怀疑它太类通用了。

你有邮件 (You Have Mail)

You've been tasked with adding a new business requirement. We need users to be able to pay for their products using PayPal.

您的任务是添加新的业务需求。 我们需要用户能够使用PayPal为其产品付款。

This User class is already used in multiple places like the user profile, shipping and payment features.

User类已经在多个地方使用,例如用户个人资料,运输和付款功能。

All we need to do is add the user's PayPal email address to the user. Right?

我们需要做的就是将用户的PayPal电子邮件地址添加到用户。 对?

分手 (Breaking It Up)

Usually, you will get new business requirements that require more changes to your code than this. But this is a simple example.

通常,您将获得新的业务需求,而这需要对代码进行更多更改。 但这是一个简单的例子。

If we start changing this User class so that it works with the payment feature then we risk affecting the user profile or the shipping feature (since they use this class too).

如果我们开始更改User类以使其与付款功能一起使用,则可能会影响用户个人资料或送货功能(因为他们也使用此类)。

What should we do?

我们应该做什么?

The best thing to do here is create a different user class that's used within each specific context.

最好的做法是创建一个在每个特定上下文中使用的不同的用户类。

Out of this should come classes like UserForAuthentication, UserProfileUser, ShippingUser and PaymentUser.

其中应该包括UserForAuthenticationUserProfileUserShippingUserPaymentUser

Are those models/classes going to contain similar pieces of data that all of them will need? Sure.

这些模型/类是否将包含所有它们都将需要的相似数据? 当然。

Will they also have pieces of data that are only used in one context? Sure.

他们还会有仅在一种情况下使用的数据吗? 当然。

For example, the user's id is needed everywhere.

例如,到处都需要用户的id

But, the user's home address is only ever needed by shipping. Why then, does the payment feature need access to that data? It doesn't.

但是,只有运送时才需要用户的家庭住址。 那么为什么付款功能需要访问该数据? 没有。

Here's what these classes might look like:

这些类可能如下所示:

class UserProfileUser {
    public firstName: string;
    public lastName: string;
    public id: number;
    public homeAddress: string;
    
    public getFullName(): string {
        return this.firstName + " " + this.lastName;
    }
}

class ShippingUser {
    public id: number;
    public homeAddress: string;
}

class UserForAuthentication {
    public id: number;
    public jwtToken: string;

    public decodeJwtToken(): string {
        return decode(this.jwtToken);
    }
}

class PaymentUser {
    public id: number;
    public creditCardNo: string;
}

分开分开 (Keep Separate Things Separate)

Notice that the home address is needed by UserProfileUser and ShippingUser. Is that bad?

注意, UserProfileUserShippingUser需要家庭住址。 那不好吗?

We've had it drilled into us so much that duplicating code is a bad thing. So much so, that it's this idea that's caused the problems we're talking about right now!

我们已经对它进行了深入研究,以至于重复代码是一件坏事。 如此之多,正是这个想法导致了我们现在正在谈论的问题!

Sometimes, it's better to "duplicate" code and/or data - if they are within different contexts. Again, we want to avoid coupling our features and classes together.

有时,最好“复制”代码和/或数据-如果它们在不同的上下文中。 同样,我们希望避免将功能和类耦合在一起。

Let me ask you a question:

让我问你一个问题:

Is it probable that the behavior for the home address within the user profile will be different than the behavior for it in the shipping feature?

用户个人资料中家庭住址的行为是否可能与送货功能中的行为不同?

The answer: yes.

答案: 是的。

So then, we are talking about two different things. It's the same raw data but not the same business function or concept.

因此,我们在谈论两件事。 这是相同的原始数据,但不具有相同的业务功能或概念

Shipping needs the home address so that it knows where to send products.

送货需要家庭住址,以便知道将产品寄往何处。

The user profile needs the home address so the user can update its values from a UI.

用户配置文件需要家庭住址, 以便用户可以从UI更新其值。

Not the same things.

不一样的东西。

Also, consider that it might also make sense to add an address to the PaymentUser class too. But, should this context share the same address as shipping?

另外,请考虑也将地址添加到PaymentUser类也PaymentUser 。 但是,此上下文应该与送货共享相同的地址吗?

Well, is it possible that your shipping address wouldn't be the same address you want to bill to? Sure! This happens all the time!

好吧,您的收货地址可能与您要开票的地址不同吗? 当然! 这事儿常常发生!

Using the Single Responsibility Principle, we see that these two concepts/responsibilities should be kept separate.

使用单一职责原则,我们看到这两个概念/职责应保持分开。

Also, notice that most of our pieces of data are not being shared. The JWT token, for example, is only needed for authenticating a user. Why would we ever need that piece of data inside our Shipping feature's code?

另外,请注意,我们的大多数数据都没有共享。 例如,仅JWT令牌仅用于认证用户。 为什么我们在运输功能的代码中需要这些数据?

Now, that information is isolated.

现在,该信息被隔离了。

Also, any methods that act on that data will also be moved and not inappropriately called by another feature's code.

同样,任何作用于该数据的方法也将被移动,并且不会被其他功能的代码不恰当地调用。

This was a simple example, and in most cases, this can get a little trickier than we might want. In the end, though, keeping different business concepts separate from each other will make your code easier to understand within a specific context, easier to maintain and will become less error-prone!

这是一个简单的示例,在大多数情况下,这可能比我们想要的要复杂一些。 但是,最终,将不同的业务概念彼此分开将使您的代码在特定的上下文中更容易理解,更易于维护,并且不那么容易出错!

This is an excerpt from my book  "Refactoring TypeScript: Keeping Your Code Healthy". This section of the book has more techniques for you to help deal with these kinds of dumping grounds. If you enjoyed this article then check out the book for more content like this!

这是我的书“重构TypeScript:使代码保持健康”的摘录。 本书的这一部分为您提供了更多的技巧来帮助您处理这些垃圾场。 如果您喜欢这篇文章, 请查看本书以获取更多类似内容!

You can connect with me on Twitter too.

您也可以在Twitter上与我联系

翻译自: https://www.freecodecamp.org/news/fixing-code-dumping-grounds/

代码混淆 增加垃圾代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值