-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathare-your-frameworks-bulletproof.html
252 lines (212 loc) · 15.5 KB
/
are-your-frameworks-bulletproof.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://use.fontawesome.com/afd448ce82.js"></script>
<!-- Meta Tag -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- SEO -->
<meta name="author" content="Bruno Rocha">
<meta name="keywords" content="Software, Engineering, Blog, Posts, iOS, Xcode, Swift, Articles, Tutorials, OBJ-C, Objective-C, Apple">
<meta name="description" content="Let's take a look at why it can be important to actively prevent developers from writing workarounds in a project.">
<meta name="title" content="Are your frameworks bulletproof?">
<meta name="url" content="https://swiftrocks.com/are-your-frameworks-bulletproof">
<meta name="image" content="https://swiftrocks.com/images/thumbs/thumb.jpg?4">
<meta name="copyright" content="Bruno Rocha">
<meta name="robots" content="index,follow">
<meta property="og:title" content="Are your frameworks bulletproof?"/>
<meta property="og:image" content="https://swiftrocks.com/images/thumbs/thumb.jpg?4"/>
<meta property="og:description" content="Let's take a look at why it can be important to actively prevent developers from writing workarounds in a project."/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="https://swiftrocks.com/are-your-frameworks-bulletproof"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="https://swiftrocks.com/images/thumbs/thumb.jpg?4"/>
<meta name="twitter:image:alt" content="Page Thumbnail"/>
<meta name="twitter:title" content="Are your frameworks bulletproof?"/>
<meta name="twitter:description" content="Let's take a look at why it can be important to actively prevent developers from writing workarounds in a project."/>
<meta name="twitter:site" content="@rockbruno_"/>
<!-- Favicon -->
<link rel="icon" type="image/png" href="images/favicon/iconsmall2.png" sizes="32x32" />
<link rel="apple-touch-icon" href="images/favicon/iconsmall2.png">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet">
<!-- Bootstrap CSS Plugins -->
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<!-- Prism CSS Stylesheet -->
<link rel="stylesheet" type="text/css" href="css/prism4.css">
<!-- Main CSS Stylesheet -->
<link rel="stylesheet" type="text/css" href="css/style48.css">
<link rel="stylesheet" type="text/css" href="css/sponsor4.css">
<!-- HTML5 shiv and Respond.js support IE8 or Older for HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://swiftrocks.com/are-your-frameworks-bulletproof"
},
"image": [
"https://swiftrocks.com/images/thumbs/thumb.jpg"
],
"datePublished": "2022-07-18T14:00:00+02:00",
"dateModified": "2022-07-18T14:00:00+02:00",
"author": {
"@type": "Person",
"name": "Bruno Rocha"
},
"publisher": {
"@type": "Organization",
"name": "SwiftRocks",
"logo": {
"@type": "ImageObject",
"url": "https://swiftrocks.com/images/thumbs/thumb.jpg"
}
},
"headline": "Are your frameworks bulletproof?",
"abstract": "Let's take a look at why it can be important to actively prevent developers from writing workarounds in a project."
}
</script>
</head>
<body>
<div id="main">
<!-- Blog Header -->
<!-- Blog Post (Right Sidebar) Start -->
<div class="container">
<div class="col-xs-12">
<div class="page-body">
<div class="row">
<div><a href="https://swiftrocks.com">
<img id="logo" class="logo" alt="SwiftRocks" src="images/bg/logo2light.png">
</a>
<div class="menu-large">
<div class="menu-arrow-right"></div>
<div class="menu-header menu-header-large">
<div class="menu-item">
<a href="blog">blog</a>
</div>
<div class="menu-item">
<a href="about">about</a>
</div>
<div class="menu-item">
<a href="talks">talks</a>
</div>
<div class="menu-item">
<a href="projects">projects</a>
</div>
<div class="menu-item">
<a href="software-engineering-book-recommendations">book recs</a>
</div>
<div class="menu-item">
<a href="games">game recs</a>
</div>
<div class="menu-arrow-right-2"></div>
</div>
</div>
<div class="menu-small">
<div class="menu-arrow-right"></div>
<div class="menu-header menu-header-small-1">
<div class="menu-item">
<a href="blog">blog</a>
</div>
<div class="menu-item">
<a href="about">about</a>
</div>
<div class="menu-item">
<a href="talks">talks</a>
</div>
<div class="menu-item">
<a href="projects">projects</a>
</div>
<div class="menu-arrow-right-2"></div>
</div>
<div class="menu-arrow-right"></div>
<div class="menu-header menu-header-small-2">
<div class="menu-item">
<a href="software-engineering-book-recommendations">book recs</a>
</div>
<div class="menu-item">
<a href="games">game recs</a>
</div>
<div class="menu-arrow-right-2"></div>
</div>
</div>
</div>
<div class="content-page" id="WRITEIT_DYNAMIC_CONTENT">
<!--WRITEIT_POST_NAME=Are your frameworks bulletproof?-->
<!--WRITEIT_POST_HTML_NAME=are-your-frameworks-bulletproof-->
<!--Add here the additional properties that you want each page to possess.-->
<!--These properties can be used to change content in the template page or in the page itself as shown here.-->
<!--Properties must start with 'WRITEIT_POST'.-->
<!--Writeit provides and injects WRITEIT_POST_NAME and WRITEIT_POST_HTML_NAME by default.-->
<!--WRITEIT_POST_SHORT_DESCRIPTION=Let's take a look at why it can be important to actively prevent developers from writing workarounds in a project.-->
<!--DateFormat example: 2021-04-12T14:00:00+02:00-->
<!--WRITEIT_POST_SITEMAP_DATE_LAST_MOD=2022-07-18T14:00:00+02:00-->
<!--WRITEIT_POST_SITEMAP_DATE=2022-07-18T14:00:00+02:00-->
<title>Are your frameworks bulletproof?</title>
<div class="blog-post">
<div class="post-title-index">
<h1>Are your frameworks bulletproof?</h1>
</div>
<div class="post-info">
<div class="post-info-text">Published on 18 Jul 2022</div>
</div>
<p>Imagine that you're a developer in a large company working to solve a high-profile architectural problem in an app. Your team has compiled all of the company's use-cases within that particular problem and developed a framework that solves not only all of those use-cases but also some additional ones that you're expecting developers will need in the near future as the project grows. The developers of the company are on board with this change, and over a large period of time, you've written extensive documentation on how to use this new framework, instructed developers on where to find said docs, and migrated the project to use it.</p>
<div class="sponsor-article-ad-auto hidden"></div>
<p>Fast-forwarding a couple of years, the project is now in such a bad state that you're in a position in which you essentially need to throw everything away and start from scratch. To make matters worse, not only the architectural problem your framework was supposed to fix is still unsolved, it's now arguably in a much <b>worse</b> shape and considerably harder to fix than before. What in holy heaven happened here?</p>
<p>I've been witnessing projects end up in this situation over and over throughout the years, and it's always because the developers are making the same mistake: <b>they didn't account for human ingenuity.</b> It's important to always keep in mind that the main priority of most developers is to save time; when facing a coding challenge in which the correct way to go is to completely refactor their current code, even if you provide extensive documentation on how to solve that particular problem, most people’s first instinct will be to avoid that as much as possible by trying to come up with clever workarounds.</p>
<p>This is not necessarily done out of malice or ignorance. It could be very well that the developer is being pressured into following this path by external factors such as unreasonable product managers, but if you do not account for this when designing systems that will be used by other developers, you’re bound to have issues in the long run.</p>
<p>While hacky code is generally not too much of a big deal in smaller companies where it’s common practice for all developers to be aware of what everyone else is doing (thus having more space for feedback and collaboration), in the world of large companies where teams are designed to run independently from each other with minimal collaboration, workarounds are ticking time bombs. As years go by and the project evolves, these hacks and workarounds get lodged so deep into the code that your project now has entire systems written on top of them, making them so unpredictable and fragile that one point you become outright unable to make any further improvements to a system without first removing the hacks from the code. However, in large companies, the amount of work necessary to fix situations like this can be so unfeasible that there's often no choice other than to write <i>even more</i> hacks and hope for the best, leading to borderline unmanageable systems with several years of unfixable legacy code that will haunt the project and its engineers for the rest of its life.</p>
<p>In over a decade of software engineering, I have never gotten to know a single large product that didn’t have this problem. It seems that the nature of how large companies operate makes it inevitable that at one point someone will merge a dangerous workaround that will have severe consequences in the long run, but it's possible for you as a platform engineer to reduce the likelihood of this happening by designing your systems to be as <b>bulletproof</b> as possible.</p>
<p>What this means exactly depends on what you’re developing, but if we take the original example and pretend that we're developing a large-scale framework for one of these large companies, your objective should be to make it as hard as possible for people to misuse your APIs by empowering <b>static linters and implementing runtime safety checks.</b></p>
<p>The best open-source example I can give of a framework that does this is <a href="https://bazel.build/">Bazel</a>. It can be very hard to configure Bazel projects as the build system has very strict rules you need to follow in order for it to work as intended, but no matter how hard you try, you simply cannot get them wrong. I've tried to workaround Bazel rules multiple times in moments where I was <i>very</i> unwilling to refactor my files to match what Bazel wanted me to do, but I never succeeded as Bazel has linters and safety checks that stop you dead on your tracks whenever you try to do anything funny. This can feel a bit excessive at first, but it makes complete sense as one of the main features of Bazel is the ability to hermetically seal your project. If I was allowed to go forward with any of the clever workarounds I was planning to write, I would have introduced issues that in the long term would have completely ruined those projects.</p>
<div class="sponsor-article-ad-auto hidden"></div>
<p>This practice has a clear downside; it massively reduces the team's productivity when facing issues involving these frameworks. On the other hand, doing this can actually open up the way for you to develop intelligent systems that actually <i>increase</i> developer productivity in the long run, and the most interesting example of this happening is how Xcode's <i>Automatic Reference Counting</i> system came to be.</p>
<p>At the beginning of the platform, reference counting on iOS used to be a completely manual process that was very easy to get wrong. Apple started helping developers by creating a series of static checks on Xcode that was able to detect and block developers from introducing some of the most common mistakes, and as they improved this system, they realized at one point that it became <i>so good</i> at reference counting that it wasn't necessary to have developers do it manually anymore. You still need to be careful with other forms of memory mistakes like retain cycles, but when it comes to general memory management, the process is now so automated and abstracted from you that it's being deemed unnecessary for new developers to even learn that this is a thing.</p>
<p>While we cannot ignore the fact that these safety procedures can be extremely detrimental to productivity in the beginning, when it comes to large established projects, I'd argue that this is a very needed trade-off to ensure the project can continue to smoothly evolve as the years go by. Dangerous legacy codes are one of the biggest walls to overcome when maintaining large projects, and actively preventing them from being introduced can save you and the company countless hours of work in the long run.</p>
</div>
</div>
<div class="blog-post footer-main">
<div class="footer-logos">
<a href="https://swiftrocks.com/rss.xml"><i class="fa fa-rss"></i></a>
<a href="https://twitter.com/rockbruno_"><i class="fa fa-twitter"></i></a>
<a href="https://github.com/rockbruno"><i class="fa fa-github"></i></a>
</div>
<div class="footer-text">
© 2025 Bruno Rocha
</div>
<div class="footer-text">
<p><a href="https://swiftrocks.com">Home</a> / <a href="blog">See all posts</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Blog Post (Right Sidebar) End -->
</div>
</div>
</div>
<!-- All Javascript Plugins -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/prism4.js"></script>
<!-- Main Javascript File -->
<script type="text/javascript" src="js/scripts30.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-H8KZTWSQ1R"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-H8KZTWSQ1R');
</script>
</body>
</html>