5 ms·
Reminded me of 'Object Calisthenics' by Jeff Bay. Basically an exercise for a toy project where you adhere to 9 rules: 1. Only One Level Of Indentation PerMeth
by 3pm 4y ago
Reminded me of 'Object Calisthenics' by Jeff Bay. Basically an exercise for a toy project where you adhere to 9 rules:
1. Only One Level Of Indentation PerMethod
2. Don’t Use The ELSE Keyword
3. Wrap All Primitives And Strings
4. First Class Collections
5. One Dot Per Line
6. Don’t Abbreviate
7. Keep All Entities Small
8. No Classes With More Than Two InstanceVariables
9. No Getters/Setters/Properties
https://williamdurand.fr/2013/06/03/object-calisthenics/ https://williamdurand.fr/2013/06/03/object-calisthenics/
- BlargMcLarg 4y ago>Wrap All Primitives And Strings Gah. I've seen the other side of this, a few people far too trigger happy to make FivePlusVeryLongNounVO/DTO for every little thing, and it gave me some new appreciation towards tuples and primitives. Sometimes you really don't want to go into another new file for an object type which is used in only one specific place. Especially with >Don’t Abbreviate Meaning the variable name will end up long anyway. With tuples, you get deconstruction without the hassle, too.
- 3pm 4y ago> Gah. I've seen the other side of this, a few people far too trigger happy to make FivePlusVeryLongNounVO/DTO for every little thing, and it gave me some new appreciation towards tuples and primitives. Sometimes you really don't want to go into another new file for an object type which is used in only one specific place. The rules are an exercise for a toy project. Like all similar 'rules' they are just hints to make you think. When done with the exercise, and you see a string with a social security number in a production code, you may consider creating a dedicated SocialSecurityNumber class. The class will guarantee a well formed social security number according to official rules. The class may even offer Area, Group and Serial parts of the social as separate fields. The class may decide to use a string or integers internally, but that would never be exposed to the class consumers. All the code that uses SocialSecurityNumber will not have to guess whether string is valid, if it has dashes etc. The same reason you use built-in types like an Integer (as oppose to a tuple of 4 bytes or 32 bits).
- BlargMcLarg 4y agoYour example breaks down the moment you put it back in context. SocialSecurityNumber works because it's going to be used across multiple subcontexts. The same reason Vector2 works over using (x, y) tuples everywhere. I'm specifically mentioning one specific place. This now requires you to go to a different file to see what's up, for every time you need HighlySpecificModelWithOnlyStringAndInt, and most naming doesn't help provide context. All that's happening here is moving vertical navigation to navigating different files. It's a remnant of a time people wanted more specification than object[], but valuetuples didn't exist yet (C#). And even then, SSN is a pretty well known abbreviation. So your example is also far too favorable compared to most extreme yet real examples.
- 3pm 4y agoYou seem to be fixated at knowing what objects consist of and you seem to stop at a fairly arbitrary level - primitives provided by the language (int, string etc). Why not go all the way down to bits? I find that a well designed Value object [0] makes me more productive because I specifically don't need to know how it is implemented internally, only the exposed interface. Examples: ZonedDateTime PhoneNumber SocialSecurity Guid EmailAddress Point Url ExpiredCoupon Regarding one specific place, if I only need to know date time and its zone in one specific place, would you recommend Tuple<int, int, int, int, int, int, int, string> instead of ZonedDateTime? [0] https://martinfowler.com/bliki/ValueObject.html https://martinfowler.com/bliki/ValueObject.html [1] https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDat...
- overgard 4y agoOof, these all seem absurd to me. > 1. Only One Level Of Indentation Per Method One level of indentation just leads to an explosion of tiny one-use methods with weird names, and now you can't read the code linearly. You will almost certainly never reuse these tiny methods, especially since you're likely consigning them to an instance of a class instead of a free function, so all you've done is forced people to jump around a lot. > 2. Don’t Use The ELSE Keyword Not using the else statement just obscures the fact that there's a branch in the code. Obscuring something important seems to be the opposite of what you should do. > 3. Wrap All Primitives And Strings Ugh, that seems verbose and clunky, especially in a language like Java without operator overloading. I'm all for type aliases or typedef's, or, creating a class if the builtin primitives don't work (I think a Money class makes sense because you don't exactly want to use a float, for instance). But just putting wrappers all over the place sounds grotesque. > 4. First Class Collections: Any class that contains a collection should contain no other member variables Why even have a class then? Why not just have functions that operate on a collection? It's much more generic that way, since if you're using iterators or an abstract collection interface, you can potentially allow the user to choose the exact data structure, and you avoid the ceremony of creating a new type that's again just a wrapper. > 5. One Dot Per Line... Basically, the rule says that you should not chain method calls. This is the first one I roughly agree with, but I wouldn't consider it a hard rule. Chaining .map and .filter together for instance is a very common pattern. > 6. Don’t Abbreviate min/max is just as clear as minimum and maximum. I'm not using "index" in my for loop when "i" will do. "n" is perfectly well understood as a count of things. Abbreviations when used properly make code easier to read, not harder. > 7. Keep All Entities Small... No class over 50 lines and no package over 10 files Ok, assuming the problem can't be simplified, all you've done is now fractured all that functionality into tens/hundreds of files. How is that easier to follow? Sure, there's balance in all things, but I'd probably rather read a 1000 line class than 20 small files split over 2 packages. > 8. No Classes With More Than Two Instance Variables... I thought people would yell at me while introducing this rule, but it didn’t happen They were being polite. I'll do it for them. What the fuck? The example he gives is also awful, where instead of using a string for name, he makes Name a type (ugh) with FirstName and LastName. Not only is that overly ceremonial, but it's wrong, there are plenty of names from various cultures that do not fit cleanly into FirstName and LastName. Also, what happens if he wants to store a MiddleName? That's three instance variables! Ohno! OR what if the person has like 10 middle names (this shit happens). Are we going to have 5 nested data types for that? > 9. No Getters/Setters/Properties ... My favorite rule. It could be rephrased as Tell, don’t ask. My brain feels like it's going to explode. > It is okay to use accessors to get the state of an object, as long as you don’t use the result to make decisions outside the object. Why else would you want to get the state of an object? > Any decisions based entirely upon the state of one object should be made inside the object itself. If your classes are 50 lines long, I guarantee you that other classes will be making decisions on other objects behalf. > Then again, they violate the Open/Closed Principle. I think the industry is largely realizing that this is a bad principle, as it implies inheritance. I think most people outside the enterprise java world now realize that using interfaces or free functions is largely better.
- bruce343434 4y agoDraconic