The Big Programming Thread - Page 486
| Forum Index > General Forum |
Thread Rules 1. This is not a "do my homework for me" thread. If you have specific questions, ask, but don't post an assignment or homework problem and expect an exact solution. 2. No recruiting for your cockamamie projects (you won't replace facebook with 3 dudes you found on the internet and $20) 3. If you can't articulate why a language is bad, don't start slinging shit about it. Just remember that nothing is worse than making CSS IE6 compatible. 4. Use [code] tags to format code blocks. | ||
|
Danglars
United States12133 Posts
| ||
|
Blisse
Canada3710 Posts
Anecdote time, I was working with a classmate on our operating system and we gave him the job of writing a bit of the basic scheduler (basically an array of queues simulating priority queues). Instead of abstracting the queue structure into its own class and then writing his scheduler to use that, he just wrote the queue lookups as part of the scheduler functions. For example, to set a process as ready he would create a boolean Found variable and then iterate through his queue with a for loop until he found it and then had an if statement afterwards to check if Found or not... then he would do more processing, i.e. the real work. When I confronted him about it he said that he doesn't like C and he'll refactor it later, which he never did. There are so many stories like this from other programmers I know, it's a bit silly. It might be just my perception of things, but I really find it weird that so many people don't actually like writing really clean code. I digress a bit, but yeah, I don't really find tutorials that useful anymore. Very rarely do I actually see tutorials show me code that I'm like, damn that's a sick way of doing it (i.e. that way of designing your code is really good! I dont see any flaws). It's usually better to go through Github repos or sample code (and sometimes I don't even find good sample code). Tutorials though are really good at showing you one way, the author's way, of how a problem can be solved. It's really up to you to mash the tutorial with your programming knowledge to design the code decently. For example, if you're making an Android project and you make a custom Control, like idk, a simple Calendar control or a custom Picker. Does that Picker need to be in your Android project? Or can you make it in a new independent project and link it in your build? Yes I know packages exist, but should your Calendar really be in the same codebase as your project? Sometimes yes, sometimes no, I don't think any tutorials actually talk about stuff like this. As a side note, I'm just going to write a proper JSON-RPC library in C# instead. I've kept my Dictionary String -> Func in the meantime because in my opinion it has the clearest representation of how the structure behaves. It's a judgment call based on how much time I have and other more important parts of the project to do :d The dictionary doesn't change at run-time and it doesn't need to be updated so I don't see a problem with it at the moment other than it feels funky. Thanks for the responses though, I like the reflection route though that makes things very unclearly why they're being invoked (plus debugging's a bit harder), and I was going to do the factory route when I realized it was a bit of overengineering - I would have to write a lot of wrapper functions unnecessarily :3 | ||
|
spinesheath
Germany8679 Posts
Judging from my own experience with those, only good for getting a piece of paper that says you were there. You might have better luck with it. Certainly not trustworthy as a single source. | ||
|
nunez
Norway4003 Posts
unlike your usual calls: function name ( socket name 0, argument name 0, argument name 1, ... ) function name ( socket name 1, argument name 0, argument name 1, ... ) ... the syntax for the chained calls is: function name [ socket name 0 ] ( argument name 0, argument name 1, ... ) [ socket name 1 ] ( argument name 0, argument name 1, ... ) ... for a no chained send on socket 0 with 2 const buffers f.ex: snd [ socket 0 ] ( const buffer 0, const buffer 1 ) they consist of an array subscript operator call to a const primer for desired function with the socket you wanna operate on... and then a function call operator with the arguments you wanna call it with on the returned functor. the returned functor finally returns a reference back to the const primer so you can chain. int main(){the types facilitating one-two punches look like so: class snd_pt{ //primer typeit has bugs (const& binds to temporary f.ex), is a lot of hassle and has a lot of caveats (these types exist only to facilitate the syntax within a given scope for a given thread) and some overhead(not a lot i think, nothing is being copied). however (i hope) i can generalize it pretty easily by templating on function signatures and taking function pointer in constructor instead of typing explicitly, and the syntax is so god damned cute and expressive (in my eyes) that i wanted to show. i'll make a better post on wrapper when i'm done, hopefully in a couple of weeks. | ||
|
spinesheath
Germany8679 Posts
Source: every single book/article/talk on clean code and me having to decode your abbreviation before I can think about the meaning. | ||
|
nunez
Norway4003 Posts
however i think con,rcv,snd,bnd,lsn,acc,sck_t,adr_t,buf_t,cbuf_t are fine when it's in the context of a socket wrapper. it's unambiguous... if you have to spend time decoding it you probably couldn't give much critique beyond it being too terse (which is valid ofc). i will squeeze a vowel in there for next time. the helper types are impossible, it's a quick sketch (but i doubt i'll deviate from my terseness). regardless the piece de resistance is the syntax of the socket calls. | ||
|
Blisse
Canada3710 Posts
i have been doing sockets too! they're really fun yeah, your code is impossible to read :d | ||
|
nunez
Norway4003 Posts
| ||
|
spinesheath
Germany8679 Posts
| ||
|
nunez
Norway4003 Posts
it's completely unambiguous in 3 letters and a postfix underscore t for types and prefix c for const, there is no way you could mix up the names. it's literally 12 things - 4 types, 2 parameters, 6 functions. i could name over 15 thousand things with 3 letters(no repeated letters, granted some ambiguity)! i agree it makes it harder to understand for ppl who're not familiar enough with context (hence comments), and even if you are you might still think it's heinous to look at and harder to read. whether or not it's unnecessary depends on context as well. for me it saves time and brings me great pleasure. regardless the function call syntax would be the same, and your fdbck is duly noted. | ||
|
Blisse
Canada3710 Posts
spines's point is just that you have to do a bit of extra work to convert the abbreviation to its full form, which makes things a chore to read. you usually don't want people reading your code to do more work in terms of figuring out function and variable names on top of already debugging the logic. hence the reason it's suggested to not use abbreviations for variable names. if your short term memory can hold 7 objects, holding the abbreviation to real word takes up a valuable space. if you've embedded the variable into medium long term memory then it's not such a big deal for you, but new people jumping in won't have the best time. I'm sure you already knew that though so there's really no problem here. | ||
|
nunez
Norway4003 Posts
however! this is a socket wrapper... it is providing another interface for sys/socket.h through simplification, assumption, abstraction, different error handling and ofc the chaining syntax; namespace SCK vs global namespace, uses prefixes like AF_ SOCK_ etc... sck_t<domain,type> s; vs int fd=socket(domain,type,0); adr_t<domain> vs sockaddr_** (un for AF_UNIX, in for AF_INET etc) buf_t / cbuf_t vs void*, size_t / const void*, size_t unix vs AF_UNIX (a socket domain) dgram vs SOCK_DGRAM (a socket type) acc - accept rcv - recv snd - send bnd - bind con - connect lsn - listen if you can't effortlessly guess what functions acc, con and lsn with supplied arguments and their types does in the context of a socket wrapper, or start mixing up types or functions, your initial feedback can only ever amount to 'i like the code to look more like this'. the confusion does not stem from the abbreviation, it stems from your lack of familiarity with the context! you don't know the rules of the game, and the names of the pieces won't teach you. even if acc was named the entire contents of 'man 2 accept' in camel case you would still have 0 clue how to use it for something useful except making the kernel produce error codes. | ||
|
Prillan
Sweden350 Posts
On June 01 2014 19:13 nunez wrote: hehe, yes, and i agree that it would be hard. but this is a socket wrapper... it is providing another interface for sys/socket.h through simplification, assumption, abstraction, different error handling and ofc the chaining syntax; namespace SCK vs global namespace, uses prefixes like AF_ SOCK_ etc... sck_t<domain,type> s; vs int fd=socket(domain,type,0); adr_t<domain> vs sockaddr_** (un for AF_UNIX, in for AF_INET etc) buf_t / cbuf_t vs void*, size_t / const void*, size_t unix vs AF_UNIX (a socket domain) dgram vs SOCK_DGRAM (a socket type) acc - accept rcv - recv snd - send bnd - bind con - connect lsn - listen if you can't effortlessly guess what functions acc, con and lsn with supplied arguments and their types does in the context of a socket wrapper, or start mixing up types or functions, your initial feedback can only ever amount to 'i like the code to look more like this', which i do appreciate, but... the confusion does not stem from the abbreviation, it stems from your lack of familiarity with the context! you don't know the rules of the game, and the names of the pieces won't teach you. even if acc was named the entire contents of 'man 2 accept' in camel case you would still have 0 clue how to use it for something useful except making the kernel produce error codes. Of course we understand what the abbreviations stand for, that's not the problem. The problem is that it makes the brain take a detour when reading the code. | ||
|
netherh
United Kingdom333 Posts
On June 01 2014 17:11 nunez wrote: it matters if you know the context, the 4 types and 6 functions have 1 to 1 (1 to 2, size_t and void* / const void* in the case of buf_t and cbuf_t) mappings with your run-of-the-mill socket shenanigans. the interfaces are simpler, i cut out functionality or hid it with default behaviour (protocol, getting adresses of senders, backlog) and abstracted (adr_t,buf_t) and the socket is no longer an ambiguous int, but an explicit socket_t<socket_domain,socket_type> (so many redundant vowels and repetitions) [it implicitly converts to an int]. it's completely unambiguous in 3 letters and a postfix underscore t for types and prefix c for const, there is no way you could mix up the names. it's literally 12 things - 4 types, 2 parameters, 6 functions. i could name over 15 thousand things with 3 letters(no repeated letters, granted some ambiguity)! i agree it makes it harder to understand for ppl who're not familiar enough with context (hence comments), and even if you are you might still think it's heinous to look at and harder to read. whether or not it's unnecessary depends on context as well. for me it saves time and brings me great pleasure. regardless the function call syntax would be the same, and your fdbck is duly noted. People generally use an auto-completion tool if they want to save typing. That way you can give things long unambiguous names that make it immediately apparent to everyone what the type is, and still only have to type three letters! Your current system messes with auto-completion too, because when I type "soc" expecting to find a socket, or "add" expecting to find address, I don't get the right type. And what does fdbck stand for? Google indicates something to do with the Netherlands, but who knows? All I know is it's not a type because it doesn't have _t. | ||
|
nunez
Norway4003 Posts
the brain takes a detour? the brain? a detour? luckily the brain can map several words to the same concept, and it doesn't have to linearly jump from the shortest word to the longest word to do it, especially when both words unambiguously conveys the same semantics in the given context! if you don't immediately understand what con means, when it conveys the semantics even clearer through the type of the argument and the return type, it is not the name that is lacking, it's your ability to parse the context. the shorter the word the faster i can read it and type it, without having to engage in a slow and error prone visual feedback process with the computer screen. bloody conformists! ;> | ||
|
Prillan
Sweden350 Posts
On June 01 2014 19:50 nunez wrote: i interpreted both blisse and spine as having trouble with the abbreviations to the point where they would have to invest to understand code. the brain takes a detour? the brain? a detour? luckily the brain can map several words to the same concept, and it doesn't have to linearly jump from the shortest word to the longest word to do it, especially when both words unambiguously conveys the same semantics in the given context! if you don't immediately understand what acc means, when it conveys the semantics even clearer through the type of the argument and the return type, it is not the name that is lacking, it's your ability to parse the context i think. the shorter the word the faster i can read it and type it, without having to engage in a slow and error prone visual feedback process with the computer screen. bloody conformists! ;> Yes. We haven't seen the abbreviations as much as you have so the mapping in our brains are not yet there. This means that we have to map the words consciously, hence it will take longer to read and understand. the shorter the word the faster i can read it and type it No, when the brain is trained to read words it doesn't read each letter individually but rather the entire word at the same time. The difference between adr and address is negligible. All this said, I too use abbreviations in my private code since I'm the only one expected to read it. | ||
|
Rollin
Australia1552 Posts
On June 01 2014 19:28 netherh wrote: People generally use an auto-completion tool if they want to save typing. That way you can give things long unambiguous names that make it immediately apparent to everyone what the type is, and still only have to type three letters! Your current system messes with auto-completion too, because when I type "soc" expecting to find a socket, or "add" expecting to find address, I don't get the right type. And what does fdbck stand for? Google indicates something to do with the Netherlands, but who knows? All I know is it's not a type because it doesn't have _t. I'm guessing feedback with no vowels (I think he was being sassy). | ||
|
netherh
United Kingdom333 Posts
On June 01 2014 19:50 nunez wrote: i interpreted both blisse and spine as having trouble with the abbreviations to the point where they would have to invest to understand code. the brain takes a detour? the brain? a detour? luckily the brain can map several words to the same concept, and it doesn't have to linearly jump from the shortest word to the longest word to do it, especially when both words unambiguously conveys the same semantics in the given context! if you don't immediately understand what acc means, when it conveys the semantics even clearer through the type of the argument and the return type, it is not the name that is lacking, it's your ability to parse the context i think. the shorter the word the faster i can read it and type it, without having to engage in a slow and error prone visual feedback process with the computer screen. bloody conformists! ;> To be blunt, your whole code snippet seems like you're trying to save yourself from typing connect twice in a row. But you're doing 100x the typing you'll ever save just to get it set up. (And then it needs to be maintained...) Anyway, I do feel you could do the same thing with functions that take tuples as arguments, instead of the "primer" types and operator[]:
Edit: I don't actually know if you can nest initializer lists like that, but you could probably just flatten it into {s1, m0, m1} if necessary. | ||
|
nunez
Norway4003 Posts
yes, if you are not familiar enough with the context then it would take a negligible effort to connect the dots, which would then dwarfed by the effort you'd have to make to actually understand the semantics of the call... if you are familliar with the context then the effort it would take would be negligible even in relation to the previous negligible effort, followed by an equally negligible boost in reading and writing speed and more expressive code. it is unambiguous and crystal clear, there is no confusion. maybe you think it's ugly, i wouldn't blame you, it's a pet project. i'm glad to hear you're a fellow abbreviator. imagine if you had to write receive instead of recv... oh my god, the humanity. @rollin haha, i think netherth was being sassy too! @nerterth initializer lists could work as well (and tuples also great), with the added bonus that you could pass sets to operators that only take one arg. it does look clunkier and less expressive though. is {s0,a0} being connected with {s1,a1} f.ex? what was cute about the syntax was that the socket was distinctly separated from the arguments it was gonna work on. it's expressive. chaining operators should be very familiar c++... std::cout<<"hello world"<<std::endl; the reason it's tricky is because i implemented it tricky (a fast sketch). you could make it very easy and then rely on the user to be a good boy too. also like i said i don't think would be that difficult to generalize it into two types, and resolve the types in the function call operator from the type of the supplied function pointer. it's a personal project, if i get a better idea i just chuck it out. it'll prolly be like tops 40 lines of code for a general type. | ||
|
nunez
Norway4003 Posts
here's the more general version of the one-two punch of array subscript operator and function call operator, sc2 themed. the infestor_t is the primer and the fungaled_t is the executor. the fungal_t (i hope) can't be moved from callsite, so hard to misuse. since it inherits the damage_t calls to function call operators will resolve to the damage_t instead. there's no chaining here, but it will be easy to add and is "totally safe" since we are not allowed to move from callsite anymore (and the infestor_t wont go out of scope). the rest is just added to produce the contrived example. ~20 loc by my count (way spread out here, only infestor_t is the relevant type). can inject behaviour through template parameter (here damage_t) and through the type of unit the array subscript operator is called with (here unit_t). like in this example the template parameter can also be dependant on the latter (get race and armor). maybe ~20 more to specialize behaviour for sockets or sth. //unit race modifier, higher is better sry formatting here failed. i don't think it's that hard to make a skinny framework to facilitate it, but doesn't mean it's any good ofc. it lets you write socket operations in a tiny, tiny EDSL, which is cool, at the cost of the awkwardness in producing it. | ||
| ||