40 ms·
Developers spend most of their time figuring the system out
- tudorgirba 6y agoIndeed they do!
- kitkat_new 6y agoPut more time into it at the beginning and save a lot of time later Rust is ideal for that if you have the opportunity to use it
- tudorgirba 6y agoWhat exactly would you put time into? And in what way do you see Rust having any meaningful influence on how one can figure a system out?
- kitkat_new 6y agoit's about reducing maintenance costs - Rust reduces how much you have to figure out later
- jokethrowaway 6y agoThe down-votes on your post are probably by people who are not happy with the status of tooling / debugging / IDEs for rust - but I totally see your point. A lot of time spent maintaining / understanding the codebase is time spent thinking about edge cases and about what can go wrong. I had a similar experience with Haskell, but in Haskell you also have to think about laziness and what the computer will actually try to do, which complicates things a bit.
- vasilakisfil 6y agoI use Rust everyday in the past 15 months. The programming language is just a very small part of the whole picture. Usually you integrate with many 3rd party systems that don't always provide all the guarantees they claim (so you get many edge cases) and understanding these things is not trivial. If it was only for understanding the code it would be easy. And actually having worked with both Rust and Ruby, the easiness of binding.pry and debugging is unbeatable. Rust gives you guarantees how the code behave, but when you have input from external sources (user input or external service input), it's much easier to understand what's happening (=debug) in a dynamic language.
- tudorgirba 6y agoThat is an interesting take. In fact, I argue that people should always choose a technology by how easy it is to figure a problem out two years into development. If you find Pry useful, I'd be curious what you think about Glamorous Toolkit.
- alpaca128 6y ago> it's much easier to understand what's happening (=debug) in a dynamic language. I would argue the opposite. It's easier to understand what's happening when you know at a glance what datatypes are involved, whether they're used by value or reference and how each case is handled. When I last worked with Python it was rather time consuming to fix bugs that crashed a script at some point after 10 minutes of processing, caused by code that would have thrown a clear compiler error in some languages and would have been fixed in seconds. And when I look at e.g. a Rust function signature I immediately see what kind of data is used as arguments and what's passed back in the result. Meanwhile in JavaScript you just need to forget a symbol in a check and suddenly it won't know the difference between "false", "null" and "undefined". You are right about integrating third-party systems, but I still prefer the approach where possible issues are discovered as early as possible.
- valenterry 6y ago> whether they're used by value or reference Or even better, if both is the same. That's the reason why, as much as I like Rust, I would never use it for a project where performance is not critical.
- pdimitar 6y agoRust is absolutely amazing and made me a much better programmer. But programmer ergonomics don't seem like a focus of their team currently. I can only hope for Rust 202X edition that can introduce new syntax / deprecate another and make certain things clearer (even if that means explicit with a little writing here and there). Lifetimes and traits in particular need a lot of upfront investment to grok intuitively, and the fact that some core aspects of the language are implied can later hit your assumptions really hard and confuse you for a while. At least that's happened to me, maybe I am just dumb and mediocre though.
- tannhaeuser 6y agoThe (unrelated topic)-to-Rust-fanboyism hop count is strong on this subthread. The amount of brain wankery you initially put in your architecture is inversely proportional to onboarding time for new staff. This problem is no stranger to Java (and Rust, it seems) projects.
- hertzrat 6y agoThe hard part is talking to hiring managers or potential clients about this without sounding like an idiot who doesn’t know how to put his or her shoes on the right feet. What do other people do in those situations to communicate this?
- dstick 6y agoThey lie?
- tudorgirba 6y ago:) That is intriguing. What do you mean?
- WJW 6y agoYou tell the managers that you will spend no time at all on figuring out the system because you are just that good. Of course, you will still need to spend some time on it. Hopefully nobody will look into it too closely, but even if they do, you can claim that that time was already part of the "fixing the problem" phase. Most managers will not look into the matter too closely, because if they find no wrongdoing then it was wasted time and if they do find it then they have to spend even more time to find a new freelancer. (And possibly take a reputational hit for hiring the wrong person in the first place)
- chriszhang 6y agoI have not faced this problem. I say that there will be a learning curve to understand the product before a new developer can start fixing bugs or adding enhancements. Managers have always understood it. For contractors too the learning curve is part of the deal. The contractors get paid by the hour when they are climbing the learning curve. Managers seem fine with it.
- tudorgirba 6y agoWhat is typically considered an acceptable learning cost / duration in your experience? I am not asking because I do not agree that there is a learning curve (we call it assessment), I am asking because I am curious what people expect.
- konjin 6y ago>We created Glamorous Toolkit to provide a concrete start for the "how not to read code" conversation. Glamorous Toolkit is a moldable development environment that makes it possible to create custom tools about software systems inexpensively. That was the most blatant blogversising I have ever seen.
- tpxl 6y agoIt's free and seems to be experimental, so I don't see an issue.
- jarmitage 6y agoGlamorous Toolkit (https://gtoolkit.com https://gtoolkit.com) by feenk, which embodies the thesis of this blog post, is in my opinion the most exciting working development environment in decades. I think in 5-10 years people will be pointing to it as having a huge impact on the industry. I implore anyone serious about changing how software development works to digest Andrei Chis' thesis Moldable Tools: http://scg.unibe.ch/archive/phd/chis-phd.pdf http://scg.unibe.ch/archive/phd/chis-phd.pdf Once you understand the consequences of reducing the cost of specialised tool development by orders of magnitude, it becomes obvious that a qualitative change in experience follows, that brings us much closer to what people like Engelbart were searching for.
- vanderZwan 6y ago> Glamorous Toolkit is implemented in Pharo, but it's made to work for many languages. Ooooh, now I am interested. I really enjoyed exploring Pharo but couldn't combine it with work. But getting to play with Pharo for a work-environment while still being able to do my day job sounds very appealing
- tudorgirba 6y agoYep. It can be directly used in several scenarios for systems built in all sorts of technologies. Join the conversation :).
- bmitc 6y agoThanks for the links and references! I am very interested in these things. One of the things I hate most about being a software developer is the tool infrastructure. I want documentation that’s accurate (actually, that would save probably at least 50% of my time), interactive documentation and debugging, little GUIs that help with various tasks, etc. I am actually working on my own vision of this, but it is slow going.
- jarmitage 6y agoYou are not alone :) https://futureofcoding.org/ https://futureofcoding.org/ Good luck!
- Glench 6y agoCouldn't agree more. I think we should redesign programming so that it is primarily a method of communicating between humans. If that becomes the focus, we can use the best methods we have of communicating words, graphics, and interactivity to explain complex systems. One of my own projects in this area is a prototype where I made the best possible explanation of a JavaScript library I could: https://glench.github.io/fuzzyset.js/ui/ https://glench.github.io/fuzzyset.js/ui/
- abacadaba 6y agoah perfect i was just about to implement cosine similarity in js :)
- elviejo 6y agoI also agree... and Gerald Sussman also agree with: "programs should be done for humans to understand, and incidentally for computers to execute." and also Knuth agreed, and that is why he invented literate programming. But why literate programming isn't more popular is beyond me.
- amelius 6y ago> "programs should be done for humans to understand, and incidentally for computers to execute." And shareholders to make money.
- brlewis 6y ago> why literate programming isn't more popular is beyond me I saw this topic brought up in a video I was watching yesterday https://youtu.be/SzA2YODtgK4?t=1519 https://youtu.be/SzA2YODtgK4?t=1519 There are 2 reasons: 1. Programmers and code review tools are not very good at making sure comments and documentation are updated when code is. 2. People see literate programming as primarily for documentation-focused or teaching purposes. The statistics in the article we're commenting on suggest that more software systems should be documentation/teaching focused, since the "learning the system" phase is where most of the time goes.
- 6y ago
- TbobbyZ 6y agoThis is my situation right now on a contract I started a few months ago. A consultancy was hired and spent over a year building a system. All the in-house employees don’t really know how it works, it’s essentially a black box to them. So I’m digging through the code to make sense of it and no one from the business can give me test data that reflects what the system was meant to handle. Only thing I can really do is best guess and slowly learn how the business operates while at the same time fix bugs and launch new features.
- jrochkind1 6y agoReading this leads me to wonder: Is a large part of what makes a "5% programmer" or whatever, that they are so much better at comprehension/figuring-it-out, and retaining what they've figured out for next time?
- jarmitage 6y agoThere will always be some who are freakishly good at manipulating visual symbols on a computer and in their heads. Those people are practically exalted today, whereas their existence should indicate that for the vast majority of people, computers are inhumane and inefficient in the Bret Victor sense: http://worrydream.com/TheHumaneRepresentationOfThought/note.html http://worrydream.com/TheHumaneRepresentationOfThought/note....
- mercer 6y agoI don't consider myself a "5% programmer", but I'd definitely agree that one of the big measures of my improvement as programmer had to do with my ability to quickly figure out how a system works, and my ability to manage the mental models involved. Compared to who I was, say, ten years ago, I'm better at grokking the system in general. But for many projects keeping the entire thing in my head is impossible, so another thing I feel I've gotten better at over time is how to figure out which part of the system I need to hold in my head as I work on things.
- MarkLowenstein 6y agoRelated theory I've had rattling around my brain recently: a programmer's career velocity is strictly correlated with the percentage of code that they deal with every day that is code of their own making, vs. someone else's. I always get so motivated and productive when I'm building off my own stuff, and pretty grumpy and slow when not.
- deleted 6y ago[deleted]
- gladimdim 6y agoSome of us (me, for example :) have to spend multiple weeks a year to draw the design architecture of certain parts of the product. During engineering meetings everybody raised the same question: i commit to new area in product, how can I understand what are the components and how to do certain things? You can ask your colleagues but they might know it as well. So I decided to document main flows and designs in PlantUML diagrams. having these diagrams greatly improved onboarding process, cause you can quickly glance what component does what and what are the dependencies (the code base was in JS, so it is usually quite limited on refactoring/figuring out wtf is going on). But the problem with such approach is: diagram quickly gets out of date. Someone makes the change and the diagram makes no sense at all now. With what I saw in Gtoolkit, you can always query the real source code and build custom dev tools that always produce current and real overview of the system. I would love to have a starter kit for JS projects that you can drag and drop and start building your own tooling for your product.
- pdimitar 6y ago> I would love to have a starter kit for JS projects that you can drag and drop and start building your own tooling for your product. Can you elaborate on that? > But the problem with such approach is: diagram quickly gets out of date. True, but using something lighter-weight like Mermaid.JS helped me in these cases.
- folkrav 6y agoYou often see stuff as simple as a README get out of date. Lowering the barrier of entry to write documentation is hardly a bad thing, but the problem remains that said documentation takes time and work to stay relevant.
- blandflakes 6y agoThe ballerina language actually had an interesting take here, where you could generate diagrams from the code: https://ballerina.io/why-ballerina/sequence-diagrams-for-programming/ https://ballerina.io/why-ballerina/sequence-diagrams-for-pro...
- 6y ago
- indymike 6y agoAt the beginning of the presentation, a slide showed the similarities between IDEs. For whatever reason, it reminded me of the setup for every intro to Smalltalk presentation I've been through. Sure enough, Glamorous Toolkit was written in Pharo, and seems to really bring a lot of the smalltalk like tooling to other languages ... and wraps it up with a notebook style UI. It's the most interesting Smalltalk thing I've seen in a while.
- tudorgirba 6y agoThank you for the kind words. It should also be said that Glamorous Toolkit works for other technologies, too.
- indymike 6y agoI'm going to try it out.
- frongpik 6y agoIn other words, the secret sauce of a scalable, in terms of people, software project is the lack of any clever bs in it: such a project uses only boring predictable patterns in everything.
- rob74 6y agoFrom my experience, when changing (or fixing) something on an existing system, I typically spend ~48% of the time figuring out where to do the change, then ~2% actually doing the change, and then another ~48% testing it and adapting unit tests broken by it.
- datavirtue 6y agoThis
- tudorgirba 6y agoI am curious what happens in the rest of the 2% :).
- pron 6y agoI've found Source Sourcetrail (https://www.sourcetrail.com/ https://www.sourcetrail.com/) an invaluable tool in aiding program comprehension, especially in C++ projects. There's another interesting program comprehension tool based on dynamic analysis (as opposed to Sourcetrail's static analysis), which I've yet to try: http://findtheflow.io/ http://findtheflow.io/
- uksmalltalk 6y agoIf anyone is interested, Tudor gave a wonderful presentation of Glamorous Toolkit at last month’s UK Smalltalk user group meeting: Part 1 https://vimeo.com/496004749 https://vimeo.com/496004749 Part 2 https://vimeo.com/498735070 https://vimeo.com/498735070
- ephaeton 6y agoSo let me get this straight: A programming environment to program programming environments in. What would be the startup cost of using this be? Hmm. Comprehending and navigating it, eh? So now, when I'm, say, doing embedded C/++ programming, I have to add yet another language to the stack, yet another toolkit, yet another environment _I have to build first_ with my preferences -- so that _another_ person getting into the project can not only use my environments, my toolkits, my code and comprehend those - but ALSO my hand built specialized for my needs programming environment? And this is supposed to _improve_ the situation? OK, I only skimmed the site, but mostly because above question keeps nagging me and the mind boggles. IOW, gtoolkit is today's sexy emacs (or, it claims to be what emacs claims/ed to be): Here's a toolkit for writing/extending/MOLDING your tool. Or, acknowledging it's smalltalk-heritaged, it's yet-another-smalltalk-IDE. It's not like the "extra work" of making your product explorable disappears with glamorous toolkit, the silver bullet. gtoolkit just offers a streamlined set of APIs for you to (comprehend, and navigate, and then) use to make your product explorable, doesn't it. So we add another layer of abstraction, work, and potential for error? What was that with complexity and abstraction? Hmm.
- tudorgirba 6y agoThanks for voicing your concerns. The parallel to Emacs is quite on point. Emacs was a great for text, but it's about time to outgrow that medium. Indeed, Glamorous Toolkit is a Smalltalk system, but the target is for it to work with all sorts of other technologies (and it does already). And yes, the claim is to spend that extra work to build tools. I understand how that can appear as coming at an extra cost. But, here is the thing: the budget for figuring the system out is already allocated. Just in the same way as it was allocated for testing. When automatic testing became a talked-about proposition, people claimed they do not have time to spend doing it because they are already busy clicking around. It turned out that automation freed much of the energy to allow people to focus on more rewarding activities. Now, it's code reading's turn to be automated. Not all of it will. Code reading is still meaningful in the small. Glamorous Toolkit is a first technology that shows how this works in practical settings. It's not theoretical. Of course, it comes with a learning cost. We estimate: - about 1 week to learn how to learn (yes, the technology can be used to learn the technology, too :)), and - about 1 month to get reasonably fluent with initial analyses. This is an investment that should be judged like any other investment. The promise we make is that the investment can be utilized over and over in many different circumstances because moldable development is universally applicable. You should not believe it. We made the technology free and open-source together with all the material around it for people to evaluate it themselves.
- silicon2401 6y agoDoes someone have advice on how to figure out a system, especially a Java API? I'm supposed to own an API at work, but I never really understood how to learn an API. Do you type out the functionality in text? Do you draw a flow diagram? Do you keep things at a class level or dive down into functions and variables? The bright side is that this API isn't very big, so I do want to use this as an opportunity to really learn it and also learn how to approach studying API's in general.
- swader999 6y agoI like to write a one pager for anything I have to grok in a serious way. Key places the code visits are summarized, I use indenting to show branching. White board helps too. Just the act of doing this is more helpful than any artifacts it produces. They decay rapidly.
- silicon2401 6y agoGreat point about the artifacts. I've definitely learned that already. Nothing makes you think hard about what documentation you choose produce like the realization that probably nobody, including yourself, will keep it up to date.
- vishnugupta 6y agoIt's beneficial to approach learning about an API top-down and bottoms-up. The context in which the API operates and then the working of the API in itself. Imagine if you were in charge of maintaining a hardware tool. I first want to know how this tool is used by various customers before learning how the tool works. 1. Begin by learning all the end-to-end product flows this API is going to be invoked within. This is the context in which your API is operating in. It also sets the stage for non-functional requirements such as latency, and availability requirements. How will end customer and business be impacted if this API were to misbehave? 2. Next speak to all the customers of this API. How do they produce the data for your API's inputs and how do they consume your API's output. You will be surprised by all sorts of creative ways in which an API gets used, not necessarily what the API was intended to begin with. But you need to support all those clients so better get to know their use cases. Also, understand how they handle your API failures. The consumers tend to make unstated assumptions about input/output validations and invariants. It's not documented anywhere but floats around as tribal knowledge. Extract that knowledge and document it somewhere. Make sure you are very clear about every single input parameter, how it's produced and its expected values as well as every single output parameter and how it's consumed. Don't forget about exceptions. Often times customers treat exceptions as just one of the expected output parameters and so actually depend on the API throwing that exception. 3. Finally, take a look at the API's implementation. Don't get frustrated if you don't understand more than 50% of the code. It's perfectly fine. Make notes of the parts that make sense and also note down those questions. Ask around. Often some parts makes absolutely no sense to you. But it is there for a reason, someone as competent as you put it in the first place. Again, ask around both within your team and the API's clients. Pay attention to the API's downstream dependencies and how their failures are handled and bubbled up to your clients. Your API's SLA depends on your downstream APIs, learn about them and ensure that it matches the expectations. 4. You also have indirect consumers of your API who depend on the side effects produced by it. Make sure you learn about them. If this API causes a side effect (such as DB update, publish a message to Kafka) then learn how those side effects are consumed. Does someone depend on it? If yes, how? Though I've described these steps in sequence I find it useful to approach all of them in parallel and over multiple iterations. At first everything is blurry and after first pass you penetrate through about 10% of cloud cover. After 4th or 5th pass you will have a reasonable understanding (~85%) to make small bug fixes.
- bluedino 6y agoThis has always been my pet peeve with jobs that won't hire people without '5-7 years experience with X' - the vast majority of these jobs do not need an EXPERT on language x, or framework y. If they do, the rest of this post does not apply. You can learn enough of a language to be dangerous in just a couple weeks. Enough to be productive in 2-3 months. However, there are 3 other things you have to learn: 1. How the code for the project you are hired for works. How it's laid out. All the weird shit about it. 2. How the framework/libraries used by the project works. Nothing to do with the project, but maybe you haven't used Angular, Swing, or Boost before. 3. How the data is laid out, and how it gets in/out of your system. What database tables are there, what's the workflow. Those 3 things are the hard part and what take 6-12 months. Learning Javascript, Ruby, or whatever language is the least of your worries.
- swader999 6y agoInsightful. The other area is often learning the intricacies of the infrastructure it runs on.
- sumtechguy 6y agoSometimes it is just the env you work in and how much they trust you. Some places 'I need a server' you will have a VM or machine on your desk in an hour. Others companies it is a 2 year processes and bunches of approvals.
- pjmlp 6y agoThe problem is that many places want to hire developers and have them deliver as soon as they get a devenv, with zero efforts on training, naturally that only works if the experience is already there.
- rory_isAdonk 6y agoExperiencing this currently, no docs on what access to apply for deployment/build systems, no explanation of graph database. Only person that's not a grad, expected to deliver sprint one.
- dfilppi 6y agoThe industry tooling for visualizing software architecture is not adequate.
- contingencies 6y agoBasically we need a spatial representation since it's heavily multidimensional, contextual and relational.
- tudorgirba 6y agoWell, the good thing is that now you have a practical platform to not wait for everyone else :).
- cmollis 6y agoI've spent almost a year with Spark and I think I'm just scratching the surface now. There are so many knobs that just configuring out just the optimal cluster configuration for production jobs took weeks of testing (so much of that is dependent on the data size and specific use-case). The docs are pretty good, but really don't detail any of 'gotchas' that you'll find in production (you have google relentlessly for those), and the hacks you put in place to deal with those, well, you're on your own. Unless you have a staff that has worked with the toolset for years with it (which we don't.. I'm basically it), you will spend weeks in a try / hack loop. All that said, it's a great toolset for its intended purpose..scala is a great language, etc, etc.. but I've spent a long time 'figuring the system out'.
- brundolf 6y agoThe tooling approach is an interesting one, but I think the most important thing remains documentation. The "treat code like data" analogy breaks down because unlike (most) data, code is a thing that was intentionally crafted, one piece at a time, by a relatively small number of people, many of whom are probably still in the building. It isn't some foreign artifact, understood by no-one, that's been measured from impersonal processes. It was made. Almost by definition someone has already had an understanding of it at some point. Reverse-engineering a new understanding from scratch - even via powerful tooling - remains a wasteful path to take compared to simply reading a (written-down) understanding that already exists.
- abeppu 6y agoSo, one aspect of this post is: a) a lot of prior work has assumed that "comprehension" and "reading" are the same and b) reading is a bad approach to understanding code. For me, this also calls to mind an old blog post from Peter Seibel about a disconnect where many of us think that we should all be reading code for our own understanding, somewhat like literature, but very few of us do and it rarely yields much. And one of the reasons why it seems that style of reading is ineffective, is that coming to an understanding of code is more like a scientific investigation than just reading prose. http://www.gigamonkeys.com/code-reading/ http://www.gigamonkeys.com/code-reading/ I agree with that point. I also agree that we need to be able to create tools that deal with software systems more easily. But I also think two other perspectives are important: - One is the historical perspective. The code-base is rarely a coherent whole. Two different areas may accomplish similar things with different tactics. The design of a component may be ill-suited to the way it is now being used. What is an intentional choice, and what is an accident? Which past choices should my current project align with? We typically read the code as it exists currently, and look at specific parts of the history only as a supplement, because even visualizing history is complex. But understanding why choices were made, and in what context, can be critical to knowing which things can now be changed. - The other is that reading code shows us a complex intensional definition, and reading tests gives us a partial view of an extensional definition (in case X we get behavior Y). But to "understand" programs enough to proficiently change them, we have to grokk something like the neighborhood around our current program: How would a given change in the code change the behavior? Being able to interactively change and re-run a program, and compare behavior before and after is in some sense like doing finite difference method differentiation.
- anaerobicover 6y agoOne thing I've found can help somewhat with the historical aspect is putting reasons for particular choices in commit messages. Including small choices, decisions that are subcomponents of the reason for the whole patch. They are forever attached exactly to that diff, and can sometimes let a spelunking maintainer differentiate accident, entropy, and intention.
- Jefro118 6y ago
- JoeAltmaier 6y agoThe difference between operator and Engineer is, you need an Engineer when it's not obvious what to do next. That's the whole job - figuring the system out and finding a solution.
- 52-6F-62 6y agoMy worst experiences have always been somewhat related to this. They need an engineer, but think they only need an operator, and they schedule (and sometimes pay) accordingly.
- contingencies 6y agoHence the value of documentation. NIH syndrome is perhaps often a rational "I need clarity and control, so I am not going to waste time grokking the existing implementations and just re-implement" decision.
- DrFell 6y agoThis will probably get worse as the value to engineers of fighting for architectural sanity diminishes in the modern semi-disposable project based job economy. I have no stake in the the companies future? OK, add another layer of abstraction to 'fix' that nonissue. Whatever. I can avoid it for as long as I can see to care.
- kiliancs 6y agoThis is why following conventions for whatever technologies you are using (not reinventing the wheel) has value. Same for documentation. Going the extra mile to document what you are doing and why, with some examples, or to update the documentation as things change, is not only valuable, but a clear sign of the maturity of a developer.
- munro 6y agoThis is so true, I Twitch streamed myself developing a game, for a total of 64 hours. And looking back, I found the parts where development slowed down is when I was confused--I almost want to yell at myself--hindsight really is 20/20. What I took away is the faster I can recognize I'm in confusion, the faster I can get out of that state--it means I really need to focus on learning what I'm not understanding, and then come up with a plan to change the actual system into what I want it to do. Another thing is, though I've really refined text editing skills, it's interesting to see yourself struggling to _simply edit text_. So while watching myself, I jotted down a few ideas of shortcuts that could help. Final thing, that I don't know how to fix, is sometimes I'm not motivated, or not in the mood, or scatter brained. Honestly, looking at myself, I don't know what my deal is. If I can just force myself to turn on the stream, then my friends will pop in and encourage me, so that has really helped. Though I'll still hit work that I'm like ugh.
- staplung 6y agoI know that the programming language is only part of the story but I do wish more programming languages put a greater emphasis on readability and maintainability rather than writing. I find it particularly annoying when a language does not allow you call functions/methods with named parameters. E.g. it's possible in python, required in Swift and impossible in Golang.
- zby 6y agoOne thing that helps me enormously in figuring the system out is running tests. I was surprised to see no mention of tests in the article.
- kelvin0 6y agoI also remember a post on HN about Chris Granger's Lightable IDE? http://lighttable.com/ http://lighttable.com/ https://www.chris-granger.com/lighttable/ https://www.chris-granger.com/lighttable/ Although as ground breaking, it does not seemt to have 'taken off' as much as it should?
- gwbdid911 6y agoWater is wet
- gwbdid911 6y agoWater is Wet.