INTPnerd
|
6 years ago
|
on: Systems that defy detailed understanding
It is true that the underlying technology used to write the code to begin with should be less forgiving. If you use a strictly typed, compiled language instead of PHP, you would have no choice but to fix a lot more of the errors because it would not compile otherwise.
Once it is running on production though, things are quite different. You need the right combination of errors being well reported and gracefully handled without aborting or breaking the rest of the functionality unnecessarily. At that point people are relying on it to get their jobs done and they will usually find ways to work around the errors and even the corrupt data this might result in so they can keep meeting their deadlines while the programmers work on fixing the problem. This is much better than those same employees not being able to do their jobs or getting payed to stand around and do nothing. I guess this attitude is largely driven by the practicalities of where I work. If the employees that rely on the code to work get behind or can't complete their work on time, our company is nailed with thousands of dollars in fines as per the contract agreements we have to agree to in order to get the business/contracts to begin with, and then our customers can't bill their customers, so they are not happy.
INTPnerd
|
6 years ago
|
on: Systems that defy detailed understanding
Even if you can reason about the code enough to come to a conclusion that seems like it must be true, that doesn't prove your conclusion is correct. When you figure something out about the code, whether through reason and research, or tinkering and logging/monitoring, you should embed that knowledge into the code, and use releases to production as a way test if you were right or not.
For example, in PHP I often find myself wondering if perhaps a class I am looking at might have subclasses that inherit from it. Since this is PHP and we have a certain amount of technical debt in the code, I cannot 100% rely on a tool to give me the answer. Instead I have to manually search through the code for subclasses and the like. If after such a search I am reasonably sure nothing is extending that class, I will change it to a "final" class in the code itself. Then I will rerun our tests and lints. If I am wrong, eventually an error or exception will be thrown, and this will be noticed. But if that doesn't happen, the next programmer who comes along and wonders if anything extends that class (probably me) will immediately find the answer in the code, the class is final. This drastically reduces possibilities for what is possible to happen, which makes it much easier to examine the code and refactor or make necessary changes.
Another example is often you come across some legacy code that seems like it no longer can run (dead code). But you are not sure, so you leave the code in there for now. In harmony with this article, you might log or in some way monitor if that path in the code ever gets executed. If after trying out different scenarios to get it to run down that path, and after leaving the monitoring in place on production for a healthy amount of time, you come to the conclusion the code really is dead code, don't just add this to your mental model or some documentation, embed it in the code as an absolute fact by deleting the code. If this manifests as a bug, it will eventually be noticed and you can fix it then.
By taking this approach you are slowly narrowing down what is possible and simplifying the code in a way that makes it an absolute fact, not just a theory or a model or a document. As you slowly remove this technical debt, you will naturally adopt rules like, all new classes must start out final, and only be changed to not be final when you need to actually extend them. Eventually you will be in a position to adopt new tools, frameworks, and languages that narrow down the possibilities even more, and further embedding the mental model of what is possible directly into the code.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
Thanks! These definitely sound like what I should explore next in my journey.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
Which languages would you say are really good for defining your own types? Would they be a good fit for the example I provided where a function needs to accept integers larger than zero? Do they also allow you to define your own operations on those types? That is the part where classes seem to be a good fit, methods are basically operations supported by a type.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
This is a good point. Right now Kotlin is my favorite language. By default classes and methods are closed for inheritance, and therefore for polymorphism. I like the way this is the default, but you can override it when/if necessary. It also has data classes, which in my opinion is what most classes should be. I think when a class is not be a good fit for data classes, this is a code smell.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
Which languages would you say are really good for defining your own types? Would they be a good fit for the example I provided where a function needs to accept integers larger than zero? Do they also allow you to define your own operations on those types? That is the part where classes seem to be a good fit, methods are basically operations supported by a type.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
In Kotlin classes and methods are closed by default, making avoiding inheritance and polymorphism the default. It also makes you mark each variable as mutable or immutable, by declaring it with a var or val, making you think more about (and enforce) state being mutable or immutable, thus avoiding a lot of state problems. It also has a concept called data classes, which works really well for most well designed classes. I now consider the case where a class is not a good candidate for data classes to be a code smell. Most classes should be a good candidate for data classes or else you are usually using classes in a way that causes more problems than it solves.
The thing is, it doesn't prevent you from creating classes or methods that are open for inheritance, nor does it prevent you from allowing mutable state, but it does use the defaults and the language design to encourage limitations that are usually good.
Perhaps they could take these concepts a step further by making classes data classes by default, having a keyword for it to not be a data class.
INTPnerd
|
6 years ago
|
on: I Don't Use Classes
The main benefit of classes is as a way to define custom types. Otherwise you are stuck with the types built into the language, which are not designed to help ensure correct program state, logic, and behavior. When you use classes in this way, I call it type oriented programming (TOP). Why would I compare classes to types? Just pass in the initial value at construction time, define the "operations" on that type by creating methods for your class, and define which other types those operations work with by setting the types of parameters those methods work with. Make the class immutable, always returning a new instance with the new updated value passed into the constructor. Why did I mention these types helping the program be more correct? This should be used as the primary form of contracts. But these contracts are very simple to use, you just specify the relevant type in the parameters and return values, and you are done defining the contract for any given method. For example, let's say a method should only work with integers larger than zero, instead of either accepting an Int or an UnsignedInt, which would allow 0, you could define your own class called PositiveInt. It would be designed to throw an exception if you pass anything smaller than 0 into the constructor. Then instead of writing code inside the method that makes sure the user of the method is following the contract, you just specify PositiveInt as the parameter type. If the contract is violated, the exception will be thrown as early as possible, before the method is even called, helping programmers catch the original source of the problem. This also makes your code more readable, because you can see exactly what each method accepts and returns just by looking at the method signature. When you start thinking this way, you will notice many core types are missing from the language, that should have been there from the beginning. Fortunately you now know how to build them yourself.
INTPnerd
|
7 years ago
|
on: The Workman Keyboard Layout Philosophy (2010)
What a stubborn Emacs user, all they had to do was switch to Vim..
INTPnerd
|
8 years ago
|
on: At 88, doctor pursues a long-ignored treatment for strokes, heart attacks
That's brilliant, using heart attacks to treat strokes
INTPnerd
|
8 years ago
|
on: Why I refuse to give up code comments
I'm not saying you should not rename it instead. I'm just suggesting that there may be times when placing a helpful comment is easier than renaming it. So you might start by adding a comment, and then consider if you can rename the method to not need the comment. But you are right that if there is an immediately obvious way to rename the method to add clarity, you could just do that and be done.
INTPnerd
|
8 years ago
|
on: Why I refuse to give up code comments
I mostly agree with you. I think the key is to always keep improving the code, don't expect or try to achieve perfection, and keep refining your concept of what makes for "improved" code.
So if you come across a method name that does not clarify enough for you what it does, and there are no comments to help, you might start by getting your questions answered, and then add comments that help clarify things. If you stop there, you have done your part, you have improved the code. The next person that comes across it, even if that person is you, is likely to have a better experience than you did. After that, if you still have more time and energy to improve it further, can try to find a better name for that method. After renaming it, you might discover the comment is no longer adding clarity, just duplication. At that point, removing the comment would be further improving the code. But if removing the comment makes it less clear, and if in your opinion the level of clarity added by the comment is worth its weight in screen space and developer read time, then removing it would be making the code worse, so you should leave it there.
I agree with what you say about context in that context is one of the most common things to not be able to express clearly enough in the code itself. However, you can still attempt to do so. An unhelpful comment is what it is, regardless of if it is expressing context or not. The same goes for a helpful comment. Sometimes a comment is helpful when the missing context is why a strange design decision was made in the code, or an unintuitive business problem users deal with that is solved by the logic in the code.
INTPnerd
|
8 years ago
|
on: My journey with Rust in 2017βββThe good, the bad, the weird
Yeah, I would have recommended Kotlin. Runs on the JVM, so benefits from the matureness of Java, but is a more modern, and better designed language. A reason to choose Rust over this is if you actually have reason to believe you will need some extra bare metal performance over a garbage collected language, or you will need multiple threads. From what I can tell, the author did not really have good reason to believe any of those things, they just wanted to stay clear of whatever was wrong with the software they used at work, which a JMV based solution should have done. I am glad it worked out for them though, and knowing Rust is a good asset to fall back on, whereas learning Kotlin should be pretty easy for them. Even so, I like that with Kotlin you can take advantage of the most mature IDE ever made InjelliJ IDEA. I think they would have completed their project faster with this. That being said, the program they ended up with sounds very fast and it probably is faster than if they wrote it in Kotlin. It was the "right" move in the sense that it seems to have worked out well for them. Was it the "best" move? Most moves are not, and they don't need to be. Whether or not Kotlin would have been better probably depends on if it was better to finish faster or have an even more blazingly fast program at the end. I don't think a Kotlin version would have been slow or had any of that wait for 30 seconds nonsense, but it probably would have been a little slower. Would that a "little slower" have mattered? It depends on who is using the program and how they are using it. It always feels nicer to have a program that feels like instantly responds to your every whim.
INTPnerd
|
8 years ago
|
on: Visual Studio Live Share
I prefer to just do screen sharing with an audio conversation going to maximize the learning and flexibility. Since I also like Sococo, I prefer to just stick to that, since that is one of the features it provides. I will now explain why.
I disagree with what was said in the video about how there are many reasons you don't want to share your entire screen. With a little care, it is actually reverse, there are many things you are missing out on if you are not sharing your entire screen. I will explain this more in a moment. I also disagree that both people being able to edit the code is a good thing. I will explain more about that in a moment. Admittedly there are situations where you actually want to control the other person's computer, but you can't have both the benefits of being able to control their computer and the benefits of not being able to, so I prefer to not be able to.
On screen sharing. The reason I prefer to share my entire screen is basically this is more flexible. There inevitably ends up being other windows and programs that have some relevant information I want to show them. It might be a web browser or something else. Prior to sharing my screen I reduce the number of monitors I'm using to 2, and I increase my font size for my editor and browser.
On computer control. I recently read an article about strong style pairing. It really resonated with me because it reminded me of something I either read or heard, can't remember which, about the current recommended way of doing mob programming. I think the main benefit is it maximizes learning. The concept is the same for both types of collaborative programming, but for some reason I never considered that it could also work with pair programming as well. Basically, you have your driver and your mapper. The driver is the one with their hands at the keyboard and mouse. The mapper is the one who tells them what to do. The mapper explains what to do at the highest level of abstraction that they both understand, and they increase the level of detail as necessary if the driver does not understand them. The driver is supposed to trust their mapper. This takes a lot of discipline to work this way, but if you are just doing screen sharing, you really don't have a choice, which makes it easier to force yourself to stick to this.
Here are the advantages of strong style pairing. It allows the mapper to keep their head on the bigger picture, while simultaneously still being the one who is really in control. Traditionally the driver would be in control, and this would free up the mapper to think on a higher level. But then it is easy for the mapper to get distracted, and there is always this nagging feeling it is not really worth having two people at the same computer. In this way, the driver is like a human interface the mapper can use to control the computer. It is as if they can talk to the computer and tell it what to do! By not having to focus on actually making the edits, they are able to plan ahead and keep more of the plan in their head. This allows them to always be ready to give the driver the next instruction as soon as the driver executes their previous one. Since the mapper is in control, they need to know how to do what they want to do. Therefore the editor and language that the driver will use, is the one the mapper wants to use. This is great because the driver can quickly pick up new editors, IDEs, and languages fairly quickly, just by driving with an expert mapper for a few days. For the same reason this makes strong style pairing work great when you want to pair experts with people at a lower skill level, which might be more frustrating otherwise. In that case, the expert is normally the driver. If the driver really has an idea they want to try out, you would switch roles for a time rather than the driver taking control.
INTPnerd
|
8 years ago
|
on: Classification of the principal programming paradigms
INTPnerd
|
8 years ago
|
on: Firefox Quantum Lands in Beta, Developer Edition
It has MRU tab switch ordering!!! Oh wait, Firefox already had that, I just didn't care because it was.. Firefox. Now that it is faster, I care. If either of those is missing I don't care about the browser. It needs to offer MRU tab switching, and be fast, and be compatible with most websites, or at least with web standards so that the websites will eventually be compatible with it. Wait, that was like 3 or 4 things... Anyway, my point is, JUST ADD MRU TO CHROME ALREADY so I can stop caring about which browser I'm using and just always use Chrome, please. This is the place where you make a wish and it comes true right?
INTPnerd
|
8 years ago
|
on: Vigil, the eternal morally vigilant programming language
I was actually kind of excited until I started reading the sample code and that it deletes code that has bugs. Of course this coming from the guy who went on a reddit rant about how not having 100% coverage is usually irresponsible.
INTPnerd
|
9 years ago
|
on: How I stopped the RSI pain that almost destroyed my programming career
"As an Emacs user"... Switch to Vim. Problem solved.
INTPnerd
|
9 years ago
|
on: Plasma Mobile β Turns your phone into a fully open hacking device
The intro video is very...interesting. They have this fast paced, upbeat music while they very slowly do things on the phone, like make phone calls. It felt like they thought we should be impressed it can make phone calls.
INTPnerd
|
10 years ago
|
on: Swift is Open Source
I like that it's open source now, but until they remove the need to mark certain references as weak or unknown, it still just feels like Apple doesn't get modern languages. Until the automatic memory management is more automatic, I will avoid swift if I can. I know many will say it is "not a big deal", but that is not true. It is an extra thing the developer needs to keep track of and to get right if they want to prevent bugs in their code. It makes programming more stressful and less fun. It is something that is very easy make a mistake with. It is a step backwards from other technologies. I know ARC is supposed to be faster than other automatic memory management techniques, but that is just an excuse. Yes, lower performance could be a problem with fully automatic memory management. But problems were meant to be solved, not dumped onto the users of your language. I'm sure it is possible to get it fast enough for most projects. There should at least be a compiler option to enable fully automatic memory management for projects that don't need that extra bit of speed. Computers, including mobile devices, are getting faster and faster. This is especially true for the iPhone and iPad.
Once it is running on production though, things are quite different. You need the right combination of errors being well reported and gracefully handled without aborting or breaking the rest of the functionality unnecessarily. At that point people are relying on it to get their jobs done and they will usually find ways to work around the errors and even the corrupt data this might result in so they can keep meeting their deadlines while the programmers work on fixing the problem. This is much better than those same employees not being able to do their jobs or getting payed to stand around and do nothing. I guess this attitude is largely driven by the practicalities of where I work. If the employees that rely on the code to work get behind or can't complete their work on time, our company is nailed with thousands of dollars in fines as per the contract agreements we have to agree to in order to get the business/contracts to begin with, and then our customers can't bill their customers, so they are not happy.